LLVM: lib/Analysis/DXILResource.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
17#include "llvm/IR/IntrinsicsDirectX.h"
22
23#define DEBUG_TYPE "dxil-resource"
24
25using namespace llvm;
26using namespace dxil;
27
29 switch (RC) {
30 case ResourceClass::SRV:
31 return "SRV";
32 case ResourceClass::UAV:
33 return "UAV";
34 case ResourceClass::CBuffer:
35 return "CBuffer";
36 case ResourceClass::Sampler:
37 return "Sampler";
38 }
40}
41
43 switch (RK) {
44 case ResourceKind::Texture1D:
45 return "Texture1D";
46 case ResourceKind::Texture2D:
47 return "Texture2D";
48 case ResourceKind::Texture2DMS:
49 return "Texture2DMS";
50 case ResourceKind::Texture3D:
51 return "Texture3D";
52 case ResourceKind::TextureCube:
53 return "TextureCube";
54 case ResourceKind::Texture1DArray:
55 return "Texture1DArray";
56 case ResourceKind::Texture2DArray:
57 return "Texture2DArray";
58 case ResourceKind::Texture2DMSArray:
59 return "Texture2DMSArray";
60 case ResourceKind::TextureCubeArray:
61 return "TextureCubeArray";
62 case ResourceKind::TypedBuffer:
63 return "TypedBuffer";
64 case ResourceKind::RawBuffer:
65 return "RawBuffer";
66 case ResourceKind::StructuredBuffer:
67 return "StructuredBuffer";
68 case ResourceKind::CBuffer:
69 return "CBuffer";
70 case ResourceKind::Sampler:
71 return "Sampler";
72 case ResourceKind::TBuffer:
73 return "TBuffer";
74 case ResourceKind::RTAccelerationStructure:
75 return "RTAccelerationStructure";
76 case ResourceKind::FeedbackTexture2D:
77 return "FeedbackTexture2D";
78 case ResourceKind::FeedbackTexture2DArray:
79 return "FeedbackTexture2DArray";
80 case ResourceKind::NumEntries:
81 case ResourceKind::Invalid:
82 return "";
83 }
85}
86
88 switch (ET) {
89 case ElementType::I1:
90 return "i1";
91 case ElementType::I16:
92 return "i16";
93 case ElementType::U16:
94 return "u16";
95 case ElementType::I32:
96 return "i32";
97 case ElementType::U32:
98 return "u32";
99 case ElementType::I64:
100 return "i64";
101 case ElementType::U64:
102 return "u64";
103 case ElementType::F16:
104 return "f16";
105 case ElementType::F32:
106 return "f32";
107 case ElementType::F64:
108 return "f64";
109 case ElementType::SNormF16:
110 return "snorm_f16";
111 case ElementType::UNormF16:
112 return "unorm_f16";
113 case ElementType::SNormF32:
114 return "snorm_f32";
115 case ElementType::UNormF32:
116 return "unorm_f32";
117 case ElementType::SNormF64:
118 return "snorm_f64";
119 case ElementType::UNormF64:
120 return "unorm_f64";
121 case ElementType::PackedS8x32:
122 return "p32i8";
123 case ElementType::PackedU8x32:
124 return "p32u8";
125 case ElementType::Invalid:
126 return "";
127 }
129}
130
132 switch (ST) {
133 case SamplerType::Default:
134 return "Default";
135 case SamplerType::Comparison:
136 return "Comparison";
137 case SamplerType::Mono:
138 return "Mono";
139 }
141}
142
144 switch (SFT) {
145 case SamplerFeedbackType::MinMip:
146 return "MinMip";
147 case SamplerFeedbackType::MipRegionUsed:
148 return "MipRegionUsed";
149 }
151}
152
154
156
159 case 16:
160 return IsSigned ? ElementType::I16 : ElementType::U16;
161 case 32:
162 return IsSigned ? ElementType::I32 : ElementType::U32;
163 case 64:
164 return IsSigned ? ElementType::I64 : ElementType::U64;
165 case 1:
166 default:
167 return ElementType::Invalid;
168 }
170 return ElementType::F32;
172 return ElementType::F64;
174 return ElementType::F16;
175 }
176
177 return ElementType::Invalid;
178}
179
183 bool GloballyCoherent, bool HasCounter)
184 : HandleTy(HandleTy), GloballyCoherent(GloballyCoherent),
185 HasCounter(HasCounter) {
186
188 RC = RC_;
189 Kind = Kind_;
190 return;
191 }
192
193 if (auto *Ty = dyn_cast(HandleTy)) {
197 } else if (auto *Ty = dyn_cast(HandleTy)) {
200 } else if (auto *Ty = dyn_cast(HandleTy)) {
202 Kind = Ty->getDimension();
203 } else if (auto *Ty = dyn_cast(HandleTy)) {
205 Kind = Ty->getDimension();
206 } else if (auto *Ty = dyn_cast(HandleTy)) {
208 Kind = Ty->getDimension();
209 } else if (isa(HandleTy)) {
212 } else if (isa(HandleTy)) {
215 } else
217}
218
220 bool isWriteable, bool isROV) {
221 Dest = isWriteable ? (isROV ? "RasterizerOrdered" : "RW") : "";
222 Dest += Name;
223}
224
227
228 switch (Kind) {
236 auto *RTy = cast(HandleTy);
238 RTy->isROV());
240 }
243 auto *RTy = cast(HandleTy);
245 false);
247 }
249 auto *RTy = cast(HandleTy);
251 RTy->isROV());
253 }
255 auto *RTy = cast(HandleTy);
256 formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
257 RTy->isROV());
259 TypeName);
260 }
262 auto *RTy = cast(HandleTy);
263 formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
264 RTy->isROV());
266 }
269 auto *RTy = cast(HandleTy);
273 TypeName);
274 }
278 auto *RTy = cast(HandleTy);
279 TypeName = formatv("SamplerState<{0}>",
282 TypeName);
283 }
290 }
292}
293
295
298}
299
302}
303
306}
307
309 switch (Kind) {
320 return true;
329 return false;
333 }
335}
336
340}
341
345}
346
348 switch (Kind) {
356 return cast(Ty)->isROV();
358 return cast(Ty)->isROV();
361 return cast(Ty)->isROV();
366 return false;
374 }
376}
377
380 return {GloballyCoherent, HasCounter, isROV(Kind, HandleTy)};
381}
382
385 return cast(HandleTy)->getCBufferSize();
386}
387
390 return cast(HandleTy)->getSamplerType();
391}
392
396
397 Type *ElTy = cast(HandleTy)->getResourceType();
398
399 uint32_t Stride = DL.getTypeAllocSize(ElTy);
401 if (auto *STy = dyn_cast(ElTy))
403 uint32_t AlignLog2 = Alignment ? Log2(*Alignment) : 0;
404 return {Stride, AlignLog2};
405}
406
409 switch (Kind) {
417 auto *RTy = cast(Ty);
418 return {RTy->getResourceType(), RTy->isSigned()};
419 }
422 auto *RTy = cast(Ty);
423 return {RTy->getResourceType(), RTy->isSigned()};
424 }
426 auto *RTy = cast(Ty);
427 return {RTy->getResourceType(), RTy->isSigned()};
428 }
440 }
442}
443
446
450 if (auto *VTy = dyn_cast(ElTy))
451 Count = VTy->getNumElements();
452 return {ET, Count};
453}
454
457 return cast(HandleTy)->getFeedbackType();
458}
461 return cast(HandleTy)->getSampleCount();
462}
463
465 return std::tie(HandleTy, GloballyCoherent, HasCounter) ==
466 std::tie(RHS.HandleTy, RHS.GloballyCoherent, RHS.HasCounter);
467}
468
470
472 if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind))
473 return true;
476 return true;
478 return true;
480 return true;
483 return true;
486 return true;
488 return true;
491 return true;
492 return false;
493}
494
498
503 } else {
507 << " HasCounter: " << UAVFlags.HasCounter << "\n"
508 << " IsROV: " << UAVFlags.IsROV << "\n";
509 }
512
515 OS << " Buffer Stride: " << Struct.Stride << "\n";
516 OS << " Alignment: " << Struct.AlignLog2 << "\n";
520 << " Element Count: " << Typed.ElementCount << "\n";
523 << "\n";
524 }
525}
526
529 assert(!Symbol && "Symbol has already been created");
530 Symbol = new GlobalVariable(M, Ty, true,
532 nullptr, Name);
533 return Symbol;
534}
535
540
542
545 auto getIntMD = [&I32Ty](uint32_t V) {
548 };
549 auto getBoolMD = [&I1Ty](uint32_t V) {
552 };
553
555 assert(Symbol && "Cannot yet create useful resource metadata without symbol");
561
568 } else {
570
571 if (RTI.isUAV()) {
576 } else {
577
578
579
582 MDVals.push_back(getIntMD(SampleCount));
583 }
584
585
591 } else if (RTI.isTyped()) {
598 }
600 }
601
603}
604
605std::pair<uint32_t, uint32_t>
609
612 bool IsUAV = RTI.isUAV();
615 bool IsROV = IsUAV && UAVFlags.IsROV;
616 bool IsGloballyCoherent = IsUAV && UAVFlags.GloballyCoherent;
617 uint8_t SamplerCmpOrHasCounter = 0;
618 if (IsUAV)
619 SamplerCmpOrHasCounter = UAVFlags.HasCounter;
622
623
624
627 Word0 |= (AlignLog2 & 0xF) << 8;
628 Word0 |= (IsUAV & 1) << 12;
629 Word0 |= (IsROV & 1) << 13;
630 Word0 |= (IsGloballyCoherent & 1) << 14;
631 Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
632
640 else if (RTI.isTyped()) {
645
646 Word1 |= (CompType & 0xFF) << 0;
647 Word1 |= (CompCount & 0xFF) << 8;
648 Word1 |= (SampleCount & 0xFF) << 16;
649 }
650
651 return {Word0, Word1};
652}
653
656 if (Symbol) {
657 OS << " Symbol: ";
659 OS << "\n";
660 }
661
662 OS << " Binding:\n"
663 << " Record ID: " << Binding.RecordID << "\n"
664 << " Space: " << Binding.Space << "\n"
665 << " Lower Bound: " << Binding.LowerBound << "\n"
666 << " Size: " << Binding.Size << "\n";
667
669}
670
671
672
675
677 return !PAC.preservedWhenStateless();
678}
679
680
681
684 CIToInfos;
685
686 for (Function &F : M.functions()) {
687 if (.isDeclaration())
688 continue;
689 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
691 switch (ID) {
692 default:
693 continue;
694 case Intrinsic::dx_resource_handlefrombinding: {
695 auto *HandleTy = cast(F.getReturnType());
697
699 if (CallInst *CI = dyn_cast(U)) {
702 cast(CI->getArgOperand(0))->getZExtValue();
704 cast(CI->getArgOperand(1))->getZExtValue();
706 cast(CI->getArgOperand(2))->getZExtValue();
708 0, Space, LowerBound, Size, HandleTy};
709
711 }
712
713 break;
714 }
715 }
716 }
717
719 const auto &[LCI, LRBI, LRTI] = LHS;
720 const auto &[RCI, RRBI, RRTI] = RHS;
721
722
725
726 return std::tie(LRC, LRBI, LRTI) < std::tie(RRC, RRBI, RRTI);
727 });
728 for (auto [CI, RBI, RTI] : CIToInfos) {
729 if (Infos.empty() || RBI != Infos.back())
730 Infos.push_back(RBI);
731 CallMap[CI] = Infos.size() - 1;
732 }
733
734 unsigned Size = Infos.size();
735
736 FirstUAV = FirstCBuffer = FirstSampler = Size;
738 for (unsigned I = 0, E = Size; I != E; ++I) {
741 if (RTI.isUAV() && FirstUAV == Size) {
742 FirstUAV = I;
743 NextID = 0;
744 } else if (RTI.isCBuffer() && FirstCBuffer == Size) {
745 FirstCBuffer = I;
746 NextID = 0;
747 } else if (RTI.isSampler() && FirstSampler == Size) {
748 FirstSampler = I;
749 NextID = 0;
750 }
751
752
754 }
755}
756
759 for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
760 OS << "Binding " << I << ":\n";
763 OS << "\n";
764 }
765
766 for (const auto &[CI, Index] : CallMap) {
767 OS << "Call bound to " << Index << ":";
768 CI->print(OS);
769 OS << "\n";
770 }
771}
772
773
774
775AnalysisKey DXILResourceTypeAnalysis::Key;
776AnalysisKey DXILResourceBindingAnalysis::Key;
777
782 Data.populate(M, DRTM);
784}
785
790
791 DBM.print(OS, DRTM, M.getDataLayout());
793}
794
795void DXILResourceTypeWrapperPass::anchor() {}
796
799}
800
802 "DXIL Resource Type Analysis", false, true)
804
807}
808
813}
814
816
820}
821
824
825 DRTM = &getAnalysis().getResourceTypeMap();
826 Map->populate(M, *DRTM);
827
828 return false;
829}
830
832
834 const Module *M) const {
835 if (!Map) {
836 OS << "No resource map has been built!\n";
837 return;
838 }
839 Map->print(OS, *DRTM, M->getDataLayout());
840}
841
842#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
845#endif
846
848 "DXIL Resource Binding Analysis", false, true)
850
853}
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned)
static StringRef getResourceClassName(ResourceClass RC)
static StringRef getElementTypeName(ElementType ET)
static void formatTypeName(SmallString< 64 > &Dest, StringRef Name, bool isWriteable, bool isROV)
static std::pair< Type *, bool > getTypedElementType(dxil::ResourceKind Kind, TargetExtType *Ty)
static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty)
static StringRef getResourceKindName(ResourceKind RK)
static StringRef getSamplerTypeName(SamplerType ST)
static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallString class.
Class for arbitrary precision integers.
API to communicate dependencies between analyses during invalidation.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class represents a function call, abstracting a target machine's calling convention.
static Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, const DataLayout &DL) const
DXILBindingMap run(Module &M, ModuleAnalysisManager &AM)
Gather resource info for the module M.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
~DXILResourceBindingWrapperPass() override
DXILResourceBindingWrapperPass()
void print(raw_ostream &OS, const Module *M) const override
print - Print out the internal state of the pass.
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv)
DXILResourceTypeWrapperPass()
A parsed version of the target data layout string in and methods for querying it.
@ ExternalLinkage
Externally visible function.
ImmutablePass class - This class is used to provide information that does not need to be run.
This is an important class for using LLVM in a threaded context.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDString * get(LLVMContext &Context, StringRef Str)
Align getAlignment() const
Return alignment of the basic block.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
A Module instance is used to store all the information related to an LLVM module.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Class to represent struct types.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
The instances of the Type class are immutable: once they are created, they are never changed.
unsigned getIntegerBitWidth() const
static IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
static IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
StringRef getName() const
Return a constant reference to the value's name.
void setBindingID(unsigned ID)
GlobalVariable * createSymbol(Module &M, StructType *Ty, StringRef Name="")
std::pair< uint32_t, uint32_t > getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const
TargetExtType * getHandleTy() const
MDTuple * getAsMetadata(Module &M, dxil::ResourceTypeInfo &RTI) const
void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const
uint32_t getMultiSampleCount() const
uint32_t getCBufferSize(const DataLayout &DL) const
bool operator<(const ResourceTypeInfo &RHS) const
bool isMultiSample() const
dxil::SamplerType getSamplerType() const
TypedInfo getTyped() const
StructType * createElementStruct()
StructInfo getStruct(const DataLayout &DL) const
ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC, const dxil::ResourceKind Kind, bool GloballyCoherent=false, bool HasCounter=false)
dxil::SamplerFeedbackType getFeedbackType() const
bool operator==(const ResourceTypeInfo &RHS) const
dxil::ResourceKind getResourceKind() const
void print(raw_ostream &OS, const DataLayout &DL) const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ RRC
Y = RRC X, rotate right via carry.
ResourceKind
The kind of resource for an SRV or UAV resource.
@ RTAccelerationStructure
ElementType
The element type of an SRV or UAV resource.
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
void initializeDXILResourceTypeWrapperPassPass(PassRegistry &)
ModulePass * createDXILResourceTypeWrapperPassPass()
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void initializeDXILResourceBindingWrapperPassPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
unsigned Log2(Align A)
Returns the log2 of the alignment.
ModulePass * createDXILResourceBindingWrapperPassPass()
A special type used by analysis passes to provide an address that identifies that particular analysis...
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
dxil::ElementType ElementTy