24#include "llvm/IR/IntrinsicsDirectX.h"
35#define DEBUG_TYPE "dxil-resource-access"
48 for (
auto *Handle : Handles) {
49 std::string HandleStr;
51 Handle->print(HandleOS);
56 "Resource access is not guaranteed to map to a unique global resource"));
65 assert((
II->getIntrinsicID() == Intrinsic::dx_resource_getpointer ||
66 II->getIntrinsicID() == Intrinsic::dx_resource_getbasepointer) &&
67 "Resource access through unexpected intrinsic");
68 return Offset ?
Offset : ConstantInt::get(Builder.getInt32Ty(), 0);
72 assert(
GEP &&
"Resource access through unexpected instruction");
74 unsigned NumIndices =
GEP->getNumIndices();
75 uint64_t IndexScale =
DL.getTypeAllocSize(
GEP->getSourceElementType());
76 APInt ConstantOffset(
DL.getIndexTypeSizeInBits(
GEP->getType()), 0);
78 if (
GEP->accumulateConstantOffset(
DL, ConstantOffset)) {
81 ConstantInt::get(
DL.getIndexType(
GEP->getType()), ConstantOffset);
83 }
else if (NumIndices == 1) {
86 GEPOffset = *
GEP->idx_begin();
87 }
else if (NumIndices == 2) {
89 auto *IndexIt =
GEP->idx_begin();
91 "GEP is not indexing through pointer");
92 GEPOffset = *(++IndexIt);
97 if (!(IndexScale % ElemSize)) {
100 IndexScale /= ElemSize;
104 GEPOffset = Builder.CreateMul(
105 GEPOffset, ConstantInt::get(Builder.getInt32Ty(), IndexScale));
107 GEPOffset = Builder.CreateUDiv(
108 GEPOffset, ConstantInt::get(Builder.getInt32Ty(), ElemSize));
111 Ptr =
GEP->getPointerOperand();
125 Value *V =
SI->getValueOperand();
126 if (V->getType() == ContainedType) {
129 "Store of whole element has mismatched address to store to");
130 }
else if (V->getType() == ScalarType) {
133 auto *
Load = Builder.CreateIntrinsic(
134 LoadType, Intrinsic::dx_resource_load_typedbuffer,
135 {
II->getOperand(0),
II->getOperand(1)});
136 auto *Struct = Builder.CreateExtractValue(
Load, {0});
138 uint64_t AccessSize =
DL.getTypeSizeInBits(ScalarType) / 8;
141 V = Builder.CreateInsertElement(Struct, V,
Offset);
146 auto *Inst = Builder.CreateIntrinsic(
147 Builder.getVoidTy(), Intrinsic::dx_resource_store_typedbuffer,
148 {II->getOperand(0), II->getOperand(1), V});
149 SI->replaceAllUsesWith(Inst);
172 Value *Handle =
II->getOperand(0);
173 Value *Coords =
II->getOperand(1);
175 Value *V =
SI->getValueOperand();
176 if (V->getType() == ContainedType) {
179 "Store of whole element has mismatched address to store to");
180 }
else if (V->getType() == ScalarType) {
184 Value *MipLevel = Builder.getInt32(0);
186 auto *
Load = Builder.CreateIntrinsic(ContainedType,
187 Intrinsic::dx_resource_load_level,
188 {Handle, Coords, MipLevel, Offsets});
190 uint64_t AccessSize =
DL.getTypeSizeInBits(ScalarType) / 8;
193 V = Builder.CreateInsertElement(
Load, V,
Offset);
198 auto *Inst = Builder.CreateIntrinsic(Builder.getVoidTy(),
199 Intrinsic::dx_resource_store_texture,
200 {Handle, Coords, V});
201 SI->replaceAllUsesWith(Inst);
210 if (!ConstantOffset || !ConstantOffset->isZero())
211 Index = Builder.CreateAdd(Index,
Offset);
215 Builder.CreateIntrinsic(Builder.getVoidTy(),
216 Intrinsic::dx_resource_store_rawbuffer,
217 {Buffer, Index, Offset, V});
225 Value *V =
SI->getValueOperand();
226 assert(!V->getType()->isAggregateType() &&
227 "Resource store should be scalar or vector type");
229 Value *Index =
II->getOperand(1);
236 if (VT && VT->getNumElements() > 4) {
238 Type *EltTy = VT->getElementType();
239 Value *Stride = ConstantInt::get(Builder.getInt32Ty(),
240 4 * (
DL.getTypeSizeInBits(EltTy) / 8));
243 for (
unsigned int I = 0,
N = VT->getNumElements();
I <
N;
I += 4) {
247 for (
unsigned int J =
I,
E = std::min(
N, J + 4); J <
E; ++J)
249 Value *Part = Builder.CreateShuffleVector(V, Indices);
279 "DXIL Store not implemented for this texture resource kind");
292static std::optional<dxil::AtomicBinOpCode>
337static std::pair<Value *, Value *>
341 Value *Index =
II->getOperand(1);
349 if (!ConstantOffset || !ConstantOffset->isZero())
350 Index = Builder.CreateAdd(Index,
Offset);
362 Value *Coords =
II->getOperand(1);
365 assert(VecTy->getNumElements() <= 3 &&
"Too many texture coordinates");
366 for (
unsigned I = 0,
E = VecTy->getNumElements();
I !=
E; ++
I)
367 CoordArgs.
push_back(Builder.CreateExtractElement(Coords,
I));
377 "Atomic operations take between one and three coordinates");
379 std::optional<dxil::AtomicBinOpCode> BinOpCode =
394 Val = Builder.CreateBitCast(Val,
OpTy);
398 Handle, Builder.getInt32(
static_cast<uint32_t>(*BinOpCode))};
407 Builder.CreateIntrinsic(
OpTy, Intrinsic::dx_resource_atomic_binop, Args);
410 Result = Builder.CreateBitCast(Result, ValTy);
433 "scalar element type");
447 "Atomic operations take between one and three coordinates");
455 Args.push_back(Compare);
456 Args.push_back(NewValue);
458 Value *Original = Builder.CreateIntrinsic(
459 NewValue->
getType(), Intrinsic::dx_resource_atomic_compare_exchange,
469 if (!EV || EV->getIndices()[0] != 0)
475 EV->replaceAllUsesWith(Original);
476 EV->eraseFromParent();
499 "scalar element type");
529 "DXIL atomicrmw not implemented for this texture resource kind");
535 "DXIL atomicrmw not implemented for this resource type");
566 "DXIL cmpxchg not implemented for this texture resource kind");
572 "DXIL cmpxchg not implemented for this resource type");
590 Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_typedbuffer,
591 {
II->getOperand(0),
II->getOperand(1)});
592 V = Builder.CreateExtractValue(V, {0});
595 uint64_t AccessSize =
DL.getTypeSizeInBits(ScalarType) / 8;
599 if (!ConstantOffset || !ConstantOffset->isZero())
600 V = Builder.CreateExtractElement(V,
Offset);
607 Builder.getInt32(0));
618 Value *Handle =
II->getOperand(0);
619 Value *Coords =
II->getOperand(1);
622 Value *MipLevel = Builder.getInt32(0);
628 Builder.CreateIntrinsic(ContainedType, Intrinsic::dx_resource_load_level,
629 {Handle, Coords, MipLevel, Offsets});
632 uint64_t AccessSize =
DL.getTypeSizeInBits(ScalarType) / 8;
636 if (!ConstantOffset || !ConstantOffset->isZero())
637 V = Builder.CreateExtractElement(V,
Offset);
644 Builder.getInt32(0));
656 if (!ConstantOffset || !ConstantOffset->isZero())
657 Index = Builder.CreateAdd(Index,
Offset);
664 Value *V = Builder.CreateIntrinsic(TypeWithCheck,
665 Intrinsic::dx_resource_load_rawbuffer,
667 return Builder.CreateExtractValue(V, {0});
675 Value *Index =
II->getOperand(1);
685 "Resource load should be scalar or vector type");
690 Type *EltTy = VT->getElementType();
691 Value *Stride = ConstantInt::get(Builder.getInt32Ty(),
692 4 * (
DL.getTypeSizeInBits(EltTy) / 8));
695 for (
unsigned int I = 0,
N = VT->getNumElements();
I <
N;
I += 4) {
713struct CBufferRowIntrin {
716 unsigned int EltSize;
717 unsigned int NumElts;
719 CBufferRowIntrin(
const DataLayout &
DL,
Type *Ty) {
722 switch (
DL.getTypeSizeInBits(Ty)) {
724 IID = Intrinsic::dx_resource_load_cbufferrow_8;
730 IID = Intrinsic::dx_resource_load_cbufferrow_4;
736 IID = Intrinsic::dx_resource_load_cbufferrow_2;
754 CBufferRowIntrin Intrin(
DL, Ty->getScalarType());
757 Value *Handle =
II->getOperand(0);
762 II->getIntrinsicID() == Intrinsic::dx_resource_getbasepointer
763 ? ConstantInt::get(Builder.getInt32Ty(), 0)
765 assert(GlobalOffset &&
"CBuffer getpointer index must be constant");
768 Value *CurrentRow = ConstantInt::get(
770 unsigned int CurrentIndex =
780 "Unexpected indirect access to resource without GEP");
784 CurrentRow = Builder.CreateAdd(GEPOffset, CurrentRow);
786 APInt ConstantOffset(
DL.getIndexTypeSizeInBits(LastGEP->getType()), 0);
787 if (LastGEP->accumulateConstantOffset(
DL, ConstantOffset)) {
788 APInt Remainder(
DL.getIndexTypeSizeInBits(LastGEP->getType()),
790 APInt::udivrem(ConstantOffset, Remainder, ConstantOffset, Remainder);
791 CurrentRow = Builder.CreateAdd(
792 CurrentRow, ConstantInt::get(Builder.getInt32Ty(), ConstantOffset));
795 assert(LastGEP->getNumIndices() == 1 &&
796 "Last GEP of cbuffer access is not array or struct access");
802 ? *LastGEP->idx_begin()
803 : Builder.CreateAdd(CurrentRow, *LastGEP->idx_begin());
808 auto *CBufLoad = Builder.CreateIntrinsic(
809 Intrin.RetTy, Intrin.IID, {Handle, CurrentRow},
nullptr, Name +
".load");
811 Builder.CreateExtractValue(CBufLoad, {CurrentIndex++}, Name +
".extract");
815 unsigned int Remaining =
816 ((
DL.getTypeSizeInBits(Ty) / 8) / Intrin.EltSize) - 1;
817 if (Remaining == 0) {
823 assert(VT->getNumElements() == 1 &&
"Can't have multiple elements here");
825 Builder.getInt32(0), Name);
833 while (Remaining--) {
834 CurrentIndex %= Intrin.NumElts;
836 if (CurrentIndex == 0) {
837 CurrentRow = Builder.CreateAdd(CurrentRow,
838 ConstantInt::get(Builder.getInt32Ty(), 1));
839 CBufLoad = Builder.CreateIntrinsic(Intrin.RetTy, Intrin.IID,
840 {Handle, CurrentRow},
nullptr,
844 Extracts.
push_back(Builder.CreateExtractValue(CBufLoad, {CurrentIndex++},
850 for (
int I = 0,
E = Extracts.
size();
I <
E; ++
I)
851 Result = Builder.CreateInsertElement(
852 Result, Extracts[
I], Builder.getInt32(
I), Name +
formatv(
".upto{}",
I));
900 if (
II->getIntrinsicID() == Intrinsic::dx_resource_updatecounter)
907 Intrinsic::dx_resource_handlefrombinding,
908 Intrinsic::dx_resource_handlefromimplicitbinding,
916 while (!Worklist.
empty()) {
919 if (!
X->getType()->isPointerTy() && !
X->getType()->isTargetExtTy())
925 for (
Use &V : Phi->incoming_values())
934 if (IID == Intrinsic::dx_resource_getpointer)
948 "Only expects a Handle as determined from collectUsedHandles.");
956 uint32_t UpperBound =
Size == UINT32_MAX ? UINT32_MAX : LowerBound +
Size - 1;
958 return hlsl::Binding(Class, Space, LowerBound, UpperBound,
nullptr);
963struct AccessIndices {
967 bool hasGetPtrIdx() {
return GetPtrIdx !=
nullptr; }
968 bool hasHandleIdx() {
return HandleIdx !=
nullptr; }
983 return {
nullptr,
II->getArgOperand(3)};
986 if (
II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
989 assert(!AccessIdx.hasGetPtrIdx() &&
990 "Encountered multiple dx.resource.getpointers in ptr chain?");
991 AccessIdx.GetPtrIdx =
II->getArgOperand(1);
1000 if (
auto It = VisitedPhis.
find(Phi); It != VisitedPhis.
end())
1001 return {
nullptr, It->second};
1003 unsigned NumEdges = Phi->getNumIncomingValues();
1004 assert(NumEdges != 0 &&
"Malformed Phi Node");
1007 std::unique_ptr<PHINode> GetPtrPhi(
1009 std::unique_ptr<PHINode> HandlePhi(
1015 if (Phi->getType()->isTargetExtTy())
1016 VisitedPhis[Phi] = HandlePhi.get();
1018 for (
unsigned Idx = 0; Idx < NumEdges; Idx++) {
1019 auto *BB = Phi->getIncomingBlock(Idx);
1022 if (AccessIdx.hasGetPtrIdx())
1023 GetPtrPhi->addIncoming(AccessIdx.GetPtrIdx, BB);
1024 HandlePhi->addIncoming(AccessIdx.HandleIdx, BB);
1028 if (GetPtrPhi->getNumIncomingValues() == 0)
1029 GetPtrIdx =
nullptr;
1030 else if (
Value *ConstantGetPtr = GetPtrPhi->hasConstantValue())
1031 GetPtrIdx = ConstantGetPtr;
1033 GetPtrIdx = GetPtrPhi.release();
1034 Builder.Insert(GetPtrIdx);
1038 if (
Value *ConstantHandle = HandlePhi->hasConstantValue())
1039 HandleIdx = ConstantHandle;
1041 HandleIdx = HandlePhi.release();
1042 Builder.Insert(HandleIdx);
1046 return {GetPtrIdx, HandleIdx};
1057 Value *GetPtrSelect =
nullptr;
1059 if (TrueAccessIdx.hasGetPtrIdx() && FalseAccessIdx.hasGetPtrIdx())
1061 Builder.CreateSelect(
Select->getCondition(), TrueAccessIdx.GetPtrIdx,
1062 FalseAccessIdx.GetPtrIdx);
1064 auto *HandleSelect =
1065 Builder.CreateSelect(
Select->getCondition(), TrueAccessIdx.HandleIdx,
1066 FalseAccessIdx.HandleIdx);
1068 return {GetPtrSelect, HandleSelect};
1079 assert(AccessIdx.hasHandleIdx() &&
1080 "Couldn't retrieve handle index. This is guaranteed by "
1081 "getAccessIndices");
1085 Builder.SetInsertPoint(Ptr->
getParent()->getFirstNonPHIIt());
1088 Builder.Insert(Handle);
1091 assert(AccessIdx.hasGetPtrIdx() &&
1092 "Couldn't retrieve getpointer index. This is guaranteed by "
1093 "getAccessIndices");
1094 auto *GetPtr = Builder.CreateIntrinsic(Ptr->
getType(),
1095 Intrinsic::dx_resource_getpointer,
1096 {Handle, AccessIdx.GetPtrIdx});
1100 "Unexpected resource access operand type");
1125 unsigned NumHandles = Handles.
size();
1126 if (NumHandles <= 1)
1129 bool SameGlobalBinding =
true;
1131 for (
unsigned Idx = 1; Idx < NumHandles; Idx++)
1132 SameGlobalBinding &=
1135 if (!SameGlobalBinding) {
1145 bool MadeChanges =
false;
1149 for (
const auto &HandleToIndex : VisitedPhis)
1150 ResourcePhis.
push_back(HandleToIndex.first);
1153 if (
I->hasNUses(0)) {
1154 I->eraseFromParent();
1169 for (
User *U :
II->users())
1173 while (!Worklist.
empty()) {
1183 assert(
SI->getValueOperand() !=
II &&
"Pointer escaped!");
1202 Dead->eraseFromParent();
1203 II->eraseFromParent();
1211 if (
II->getIntrinsicID() == Intrinsic::dx_resource_getpointer ||
1212 II->getIntrinsicID() == Intrinsic::dx_resource_getbasepointer) {
1215 (DRTM[HandleTy].isCBuffer() ||
1216 II->getIntrinsicID() != Intrinsic::dx_resource_getbasepointer) &&
1217 "dx_resource_getbasepointer should only be used by cbuffers");
1232 assert(DRTM &&
"DXILResourceTypeAnalysis must be available");
1236 if (!(MadeHandleChanges || MadeResourceChanges))
1250 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1253 return MadeHandleChanges || MadeResourceChanges;
1255 StringRef getPassName()
const override {
return "DXIL Resource Access"; }
1256 DXILResourceAccessLegacy() : FunctionPass(
ID) {}
1259 void getAnalysisUsage(llvm::AnalysisUsage &AU)
const override {
1264char DXILResourceAccessLegacy::ID = 0;
1268 "DXIL Resource Access",
false,
false)
1274 return new DXILResourceAccessLegacy();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Remove Unused Resources
static void diagnoseNonUniqueResourceAccess(Instruction *I, ArrayRef< IntrinsicInst * > Handles)
static AccessIndices getAccessIndices(Instruction *I, SmallSetVector< Instruction *, 16 > &DeadInsts, SmallDenseMap< PHINode *, PHINode * > &VisitedPhis)
static std::optional< dxil::AtomicBinOpCode > getAtomicBinOpCode(AtomicRMWInst::BinOp BinOp)
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createTextureStore(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
static Value * emitRawLoad(IRBuilder<> &Builder, Type *Ty, Value *Buffer, Value *Index, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void emitAtomicCompareExchange(IRBuilder<> &Builder, AtomicCmpXchgInst *AI, Value *Handle, ArrayRef< Value * > Coords)
static bool legalizeResourceHandles(Function &F, DXILResourceTypeMap &DRTM)
static void createTypedBufferLoad(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createTypedBufferStore(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
static SmallVector< IntrinsicInst * > collectUsedHandles(Value *Ptr)
static const std::array< Intrinsic::ID, 2 > HandleIntrins
static bool transformResourcePointers(Function &F, DXILResourceTypeMap &DRTM)
static void createTextureLoad(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void emitRawStore(IRBuilder<> &Builder, Value *Buffer, Value *Index, Value *Offset, Value *V, dxil::ResourceTypeInfo &RTI)
static Value * getNullOffsetsFor(IRBuilder<> &Builder, Value *Coords)
Build a zero-initialized offset operand matching the shape of the given coordinate operand.
static void createBufferAtomicCompareExchange(IntrinsicInst *II, AtomicCmpXchgInst *AI, dxil::ResourceTypeInfo &RTI)
static void replaceHandleWithIndices(Instruction *Ptr, IntrinsicInst *OldHandle, SmallSetVector< Instruction *, 16 > &DeadInsts, SmallDenseMap< PHINode *, PHINode * > &VisitedPhis)
static Value * traverseGEPOffsets(const DataLayout &DL, IRBuilder<> &Builder, Value *Ptr, uint64_t AccessSize)
static void createBufferAtomicBinOp(IntrinsicInst *II, AtomicRMWInst *AI, dxil::ResourceTypeInfo &RTI)
static hlsl::Binding getHandleIntrinsicBinding(IntrinsicInst *Handle, DXILResourceTypeMap &DRTM)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
static void createCBufferLoad(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static std::pair< Value *, Value * > getAtomicResourceCoords(IntrinsicInst *II, Value *PointerOperand, dxil::ResourceTypeInfo &RTI, IRBuilder<> &Builder, const DataLayout &DL)
static void createRawStores(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
static SmallVector< Value *, 3 > getTextureAtomicCoords(IntrinsicInst *II, IRBuilder<> &Builder)
static void createTextureAtomicBinOp(IntrinsicInst *II, AtomicRMWInst *AI, dxil::ResourceTypeInfo &RTI)
static void emitAtomicBinOp(IRBuilder<> &Builder, AtomicRMWInst *AI, Value *Handle, ArrayRef< Value * > Coords)
static void createRawLoads(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createAtomicCompareExchangeIntrinsic(IntrinsicInst *II, AtomicCmpXchgInst *AI, dxil::ResourceTypeInfo &RTI)
static void createAtomicBinOpIntrinsic(IntrinsicInst *II, AtomicRMWInst *AI, dxil::ResourceTypeInfo &RTI)
static Instruction * getHandleOperand(Instruction *AI)
static void createTextureAtomicCompareExchange(IntrinsicInst *II, AtomicCmpXchgInst *AI, dxil::ResourceTypeInfo &RTI)
static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI)
This file defines the DenseMap class.
static bool runOnFunction(Function &F, bool PostInlining)
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallSet class.
Class for arbitrary precision integers.
LLVM_ABI APInt udiv(const APInt &RHS) const
Unsigned division operation.
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
uint64_t getZExtValue() const
Get zero extended value.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
An instruction that atomically checks whether a specified value is in a memory location,...
Value * getNewValOperand()
Value * getCompareOperand()
Value * getPointerOperand()
an instruction that atomically reads a memory location, combines it with another value,...
BinOp
This enumeration lists the possible modifications atomicrmw can make.
@ USubCond
Subtract only if no unsigned overflow.
@ FMinimum
*p = minimum(old, v) minimum matches the behavior of llvm.minimum.
@ Min
*p = old <signed v ? old : v
@ USubSat
*p = usub.sat(old, v) usub.sat matches the behavior of llvm.usub.sat.
@ FMaximum
*p = maximum(old, v) maximum matches the behavior of llvm.maximum.
@ UIncWrap
Increment one up to a maximum value.
@ Max
*p = old >signed v ? old : v
@ UMin
*p = old <unsigned v ? old : v
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ UMax
*p = old >unsigned v ? old : v
@ FMaximumNum
*p = maximumnum(old, v) maximumnum matches the behavior of llvm.maximumnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
@ FMinimumNum
*p = minimumnum(old, v) minimumnum matches the behavior of llvm.minimumnum.
Value * getPointerOperand()
BinOp getOperation() const
LLVM Basic Block Representation.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
A parsed version of the target data layout string in and methods for querying it.
iterator find(const_arg_type_t< KeyT > Val)
Analysis pass which computes a DominatorTree.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
FunctionPass class - This class is used to implement most global optimizations.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
iterator_range< user_iterator > users()
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
bool insert(const value_type &X)
Insert a new element into the SetVector.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Type * getTypeParameter(unsigned i) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isPointerTy() const
True if this is an instance of PointerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isTargetExtTy() const
Return true if this is a target extension type.
bool isAggregateType() const
Return true if the type is an aggregate type.
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Value handle that is nullable, but tries to track the Value.
TargetExtType * getHandleTy() const
LLVM_ABI bool isStruct() const
dxil::ResourceKind getResourceKind() const
const ParentTy * getParent() const
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ RTAccelerationStructure
const unsigned CBufferRowSizeInBytes
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI Value * concatenateVectors(IRBuilderBase &Builder, ArrayRef< Value * > Vecs)
Concatenate a list of vectors.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
FunctionPass * createDXILResourceAccessLegacyPass()
Pass to update resource accesses to use load/store directly.
LLVM_ABI bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, SmallPtrSetImpl< PHINode * > *KnownNonDeadPHIs=nullptr)
If the specified value is an effectively dead PHI node, due to being a def-use chain of single-use no...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.