LLVM 22.0.0git
DXILResourceAccess.cpp
Go to the documentation of this file.
1//===- DXILResourceAccess.cpp - Resource access via load/store ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "DirectX.h"
11#include "llvm/ADT/SetVector.h"
13#include "llvm/IR/BasicBlock.h"
14#include "llvm/IR/Dominators.h"
15#include "llvm/IR/IRBuilder.h"
16#include "llvm/IR/Instruction.h"
19#include "llvm/IR/Intrinsics.h"
20#include "llvm/IR/IntrinsicsDirectX.h"
21#include "llvm/IR/User.h"
24
25#define DEBUG_TYPE "dxil-resource-access"
26
27using namespace llvm;
28
31 assert(!PrevOffset && "Non-constant GEP chains not handled yet");
32
33 const DataLayout &DL = GEP->getDataLayout();
34
35 uint64_t ScalarSize = 1;
36 if (RTI.isTyped()) {
37 Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
38 // We need the size of an element in bytes so that we can calculate the
39 // offset in elements given a total offset in bytes.
40 Type *ScalarType = ContainedType->getScalarType();
41 ScalarSize = DL.getTypeSizeInBits(ScalarType) / 8;
42 }
43
44 APInt ConstantOffset(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
45 if (GEP->accumulateConstantOffset(DL, ConstantOffset)) {
46 APInt Scaled = ConstantOffset.udiv(ScalarSize);
47 return ConstantInt::get(Type::getInt32Ty(GEP->getContext()), Scaled);
48 }
49
50 auto IndexIt = GEP->idx_begin();
51 assert(cast<ConstantInt>(IndexIt)->getZExtValue() == 0 &&
52 "GEP is not indexing through pointer");
53 ++IndexIt;
54 Value *Offset = *IndexIt;
55 assert(++IndexIt == GEP->idx_end() && "Too many indices in GEP");
56 return Offset;
57}
58
61 IRBuilder<> Builder(SI);
62 Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
63 Type *LoadType = StructType::get(ContainedType, Builder.getInt1Ty());
64
65 Value *V = SI->getValueOperand();
66 if (V->getType() == ContainedType) {
67 // V is already the right type.
68 assert(!Offset && "store of whole element has offset?");
69 } else if (V->getType() == ContainedType->getScalarType()) {
70 // We're storing a scalar, so we need to load the current value and only
71 // replace the relevant part.
72 auto *Load = Builder.CreateIntrinsic(
73 LoadType, Intrinsic::dx_resource_load_typedbuffer,
74 {II->getOperand(0), II->getOperand(1)});
75 auto *Struct = Builder.CreateExtractValue(Load, {0});
76
77 // If we have an offset from seeing a GEP earlier, use that. Otherwise, 0.
78 if (!Offset)
79 Offset = ConstantInt::get(Builder.getInt32Ty(), 0);
80 V = Builder.CreateInsertElement(Struct, V, Offset);
81 } else {
82 llvm_unreachable("Store to typed resource has invalid type");
83 }
84
85 auto *Inst = Builder.CreateIntrinsic(
86 Builder.getVoidTy(), Intrinsic::dx_resource_store_typedbuffer,
87 {II->getOperand(0), II->getOperand(1), V});
88 SI->replaceAllUsesWith(Inst);
89}
90
92 IRBuilder<> Builder(SI);
93
94 if (!Offset)
95 Offset = ConstantInt::get(Builder.getInt32Ty(), 0);
96 Value *V = SI->getValueOperand();
97 // TODO: break up larger types
98 auto *Inst = Builder.CreateIntrinsic(
99 Builder.getVoidTy(), Intrinsic::dx_resource_store_rawbuffer,
100 {II->getOperand(0), II->getOperand(1), Offset, V});
101 SI->replaceAllUsesWith(Inst);
102}
103
106 switch (RTI.getResourceKind()) {
107 case dxil::ResourceKind::TypedBuffer:
108 return createTypedBufferStore(II, SI, Offset, RTI);
109 case dxil::ResourceKind::RawBuffer:
110 case dxil::ResourceKind::StructuredBuffer:
111 return createRawStore(II, SI, Offset);
112 case dxil::ResourceKind::Texture1D:
113 case dxil::ResourceKind::Texture2D:
114 case dxil::ResourceKind::Texture2DMS:
115 case dxil::ResourceKind::Texture3D:
116 case dxil::ResourceKind::TextureCube:
117 case dxil::ResourceKind::Texture1DArray:
118 case dxil::ResourceKind::Texture2DArray:
119 case dxil::ResourceKind::Texture2DMSArray:
120 case dxil::ResourceKind::TextureCubeArray:
121 case dxil::ResourceKind::FeedbackTexture2D:
122 case dxil::ResourceKind::FeedbackTexture2DArray:
123 reportFatalUsageError("DXIL Load not implemented yet");
124 return;
125 case dxil::ResourceKind::CBuffer:
126 case dxil::ResourceKind::Sampler:
127 case dxil::ResourceKind::TBuffer:
128 case dxil::ResourceKind::RTAccelerationStructure:
129 case dxil::ResourceKind::Invalid:
130 case dxil::ResourceKind::NumEntries:
131 llvm_unreachable("Invalid resource kind for store");
132 }
133 llvm_unreachable("Unhandled case in switch");
134}
135
138 IRBuilder<> Builder(LI);
139 Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
140 Type *LoadType = StructType::get(ContainedType, Builder.getInt1Ty());
141
142 Value *V =
143 Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_typedbuffer,
144 {II->getOperand(0), II->getOperand(1)});
145 V = Builder.CreateExtractValue(V, {0});
146
147 if (Offset)
148 V = Builder.CreateExtractElement(V, Offset);
149
150 // If we loaded a <1 x ...> instead of a scalar (presumably to feed a
151 // shufflevector), then make sure we're maintaining the resulting type.
152 if (auto *VT = dyn_cast<FixedVectorType>(LI->getType()))
153 if (VT->getNumElements() == 1 && !isa<FixedVectorType>(V->getType()))
154 V = Builder.CreateInsertElement(PoisonValue::get(VT), V,
155 Builder.getInt32(0));
156
157 LI->replaceAllUsesWith(V);
158}
159
161 IRBuilder<> Builder(LI);
162 // TODO: break up larger types
163 Type *LoadType = StructType::get(LI->getType(), Builder.getInt1Ty());
164 if (!Offset)
165 Offset = ConstantInt::get(Builder.getInt32Ty(), 0);
166 Value *V =
167 Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_rawbuffer,
168 {II->getOperand(0), II->getOperand(1), Offset});
169 V = Builder.CreateExtractValue(V, {0});
170
171 LI->replaceAllUsesWith(V);
172}
173
176 switch (RTI.getResourceKind()) {
177 case dxil::ResourceKind::TypedBuffer:
178 return createTypedBufferLoad(II, LI, Offset, RTI);
179 case dxil::ResourceKind::RawBuffer:
180 case dxil::ResourceKind::StructuredBuffer:
181 return createRawLoad(II, LI, Offset);
182 case dxil::ResourceKind::Texture1D:
183 case dxil::ResourceKind::Texture2D:
184 case dxil::ResourceKind::Texture2DMS:
185 case dxil::ResourceKind::Texture3D:
186 case dxil::ResourceKind::TextureCube:
187 case dxil::ResourceKind::Texture1DArray:
188 case dxil::ResourceKind::Texture2DArray:
189 case dxil::ResourceKind::Texture2DMSArray:
190 case dxil::ResourceKind::TextureCubeArray:
191 case dxil::ResourceKind::FeedbackTexture2D:
192 case dxil::ResourceKind::FeedbackTexture2DArray:
193 case dxil::ResourceKind::CBuffer:
194 case dxil::ResourceKind::TBuffer:
195 // TODO: handle these
196 return;
197 case dxil::ResourceKind::Sampler:
198 case dxil::ResourceKind::RTAccelerationStructure:
199 case dxil::ResourceKind::Invalid:
200 case dxil::ResourceKind::NumEntries:
201 llvm_unreachable("Invalid resource kind for load");
202 }
203 llvm_unreachable("Unhandled case in switch");
204}
205
210 auto *BB = Start->getParent();
211
212 // Seed with direct users in this block.
213 for (User *U : Start->users()) {
214 if (auto *I = dyn_cast<Instruction>(U)) {
215 if (I->getParent() == BB)
216 Worklist.push_back(I);
217 }
218 }
219
220 // BFS over transitive users, constrained to the same block.
221 while (!Worklist.empty()) {
222 Instruction *I = Worklist.pop_back_val();
223 if (!Visited.insert(I).second)
224 continue;
225 Out.push_back(I);
226
227 for (User *U : I->users()) {
228 if (auto *J = dyn_cast<Instruction>(U)) {
229 if (J->getParent() == BB)
230 Worklist.push_back(J);
231 }
232 }
233 for (Use &V : I->operands()) {
234 if (auto *J = dyn_cast<Instruction>(V)) {
235 if (J->getParent() == BB && V != Start)
236 Worklist.push_back(J);
237 }
238 }
239 }
240
241 // Order results in program order.
243 unsigned Idx = 0;
244 for (Instruction &I : *BB)
245 Ord[&I] = Idx++;
246
247 llvm::sort(Out, [&](Instruction *A, Instruction *B) {
248 return Ord.lookup(A) < Ord.lookup(B);
249 });
250
251 return Out;
252}
253
255 IRBuilder<> &Builder,
256 SmallVector<Instruction *> &UsesInBlock) {
257
259 Value *Val = Phi->getIncomingValueForBlock(BB);
260 VMap[Phi] = Val;
261 Builder.SetInsertPoint(&BB->back());
262 for (Instruction *I : UsesInBlock) {
263 // don't clone over the Phi just remap them
264 if (auto *PhiNested = dyn_cast<PHINode>(I)) {
265 VMap[PhiNested] = PhiNested->getIncomingValueForBlock(BB);
266 continue;
267 }
268 Instruction *Clone = I->clone();
269 RemapInstruction(Clone, VMap,
271 Builder.Insert(Clone);
272 VMap[I] = Clone;
273 }
274}
275
277 SmallVectorImpl<Instruction *> &PrevBBDeadInsts,
278 SetVector<BasicBlock *> &DeadBB) {
279 SmallVector<Instruction *> CurrBBDeadInsts;
280 for (User *U : II->users()) {
281 auto *Phi = dyn_cast<PHINode>(U);
282 if (!Phi)
283 continue;
284
285 IRBuilder<> Builder(Phi);
287 bool HasReturnUse = isa<ReturnInst>(UsesInBlock.back());
288
289 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; I++) {
290 auto *CurrIncomingBB = Phi->getIncomingBlock(I);
291 phiNodeRemapHelper(Phi, CurrIncomingBB, Builder, UsesInBlock);
292 if (HasReturnUse)
293 PrevBBDeadInsts.push_back(&CurrIncomingBB->back());
294 }
295
296 CurrBBDeadInsts.push_back(Phi);
297
298 for (Instruction *I : UsesInBlock) {
299 CurrBBDeadInsts.push_back(I);
300 }
301 if (HasReturnUse) {
302 BasicBlock *PhiBB = Phi->getParent();
303 DeadBB.insert(PhiBB);
304 }
305 }
306 // Traverse the now-dead instructions in RPO and remove them.
307 for (Instruction *Dead : llvm::reverse(CurrBBDeadInsts))
308 Dead->eraseFromParent();
309 CurrBBDeadInsts.clear();
310}
311
313 // Process users keeping track of indexing accumulated from GEPs.
314 struct AccessAndOffset {
315 User *Access;
316 Value *Offset;
317 };
319 for (User *U : II->users())
320 Worklist.push_back({U, nullptr});
321
323 while (!Worklist.empty()) {
324 AccessAndOffset Current = Worklist.back();
325 Worklist.pop_back();
326
327 if (auto *GEP = dyn_cast<GetElementPtrInst>(Current.Access)) {
328 IRBuilder<> Builder(GEP);
329
330 Value *Offset = calculateGEPOffset(GEP, Current.Offset, RTI);
331 for (User *U : GEP->users())
332 Worklist.push_back({U, Offset});
333 DeadInsts.push_back(GEP);
334
335 } else if (auto *SI = dyn_cast<StoreInst>(Current.Access)) {
336 assert(SI->getValueOperand() != II && "Pointer escaped!");
337 createStoreIntrinsic(II, SI, Current.Offset, RTI);
338 DeadInsts.push_back(SI);
339
340 } else if (auto *LI = dyn_cast<LoadInst>(Current.Access)) {
341 createLoadIntrinsic(II, LI, Current.Offset, RTI);
342 DeadInsts.push_back(LI);
343 } else
344 llvm_unreachable("Unhandled instruction - pointer escaped?");
345 }
346
347 // Traverse the now-dead instructions in RPO and remove them.
348 for (Instruction *Dead : llvm::reverse(DeadInsts))
349 Dead->eraseFromParent();
350 II->eraseFromParent();
351}
352
356 SmallVector<Instruction *> PrevBBDeadInsts;
357 for (BasicBlock &BB : make_early_inc_range(F)) {
359 if (auto *II = dyn_cast<IntrinsicInst>(&I))
360 if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
361 phiNodeReplacement(II, PrevBBDeadInsts, DeadBB);
362
363 for (Instruction &I : BB)
364 if (auto *II = dyn_cast<IntrinsicInst>(&I))
365 if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
366 auto *HandleTy = cast<TargetExtType>(II->getArgOperand(0)->getType());
367 Resources.emplace_back(II, DRTM[HandleTy]);
368 }
369 }
370 for (auto *Dead : PrevBBDeadInsts)
371 Dead->eraseFromParent();
372 PrevBBDeadInsts.clear();
373 for (auto *Dead : DeadBB)
374 Dead->eraseFromParent();
375 DeadBB.clear();
376
377 for (auto &[II, RI] : Resources)
378 replaceAccess(II, RI);
379
380 return !Resources.empty();
381}
382
386 DXILResourceTypeMap *DRTM =
387 MAMProxy.getCachedResult<DXILResourceTypeAnalysis>(*F.getParent());
388 assert(DRTM && "DXILResourceTypeAnalysis must be available");
389
390 bool MadeChanges = transformResourcePointers(F, *DRTM);
391 if (!MadeChanges)
392 return PreservedAnalyses::all();
393
397 return PA;
398}
399
400namespace {
401class DXILResourceAccessLegacy : public FunctionPass {
402public:
403 bool runOnFunction(Function &F) override {
404 DXILResourceTypeMap &DRTM =
405 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
406 return transformResourcePointers(F, DRTM);
407 }
408 StringRef getPassName() const override { return "DXIL Resource Access"; }
409 DXILResourceAccessLegacy() : FunctionPass(ID) {}
410
411 static char ID; // Pass identification.
412 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
415 }
416};
417char DXILResourceAccessLegacy::ID = 0;
418} // end anonymous namespace
419
420INITIALIZE_PASS_BEGIN(DXILResourceAccessLegacy, DEBUG_TYPE,
421 "DXIL Resource Access", false, false)
423INITIALIZE_PASS_END(DXILResourceAccessLegacy, DEBUG_TYPE,
424 "DXIL Resource Access", false, false)
425
427 return new DXILResourceAccessLegacy();
428}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
@ Scaled
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static void phiNodeRemapHelper(PHINode *Phi, BasicBlock *BB, IRBuilder<> &Builder, SmallVector< Instruction * > &UsesInBlock)
static Value * calculateGEPOffset(GetElementPtrInst *GEP, Value *PrevOffset, dxil::ResourceTypeInfo &RTI)
static bool transformResourcePointers(Function &F, DXILResourceTypeMap &DRTM)
static void createRawLoad(IntrinsicInst *II, LoadInst *LI, Value *Offset)
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createTypedBufferLoad(IntrinsicInst *II, LoadInst *LI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static void createTypedBufferStore(IntrinsicInst *II, StoreInst *SI, Value *Offset, dxil::ResourceTypeInfo &RTI)
static SmallVector< Instruction * > collectBlockUseDef(Instruction *Start)
DXIL Resource Access
static void phiNodeReplacement(IntrinsicInst *II, SmallVectorImpl< Instruction * > &PrevBBDeadInsts, SetVector< BasicBlock * > &DeadBB)
static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI)
static void createRawStore(IntrinsicInst *II, StoreInst *SI, Value *Offset)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
static bool runOnFunction(Function &F, bool PostInlining)
#define DEBUG_TYPE
Hexagon Common GEP
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:39
This file implements a set that has insertion order iteration characteristics.
@ Struct
Class for arbitrary precision integers.
Definition: APInt.h:78
LLVM_ABI APInt udiv(const APInt &RHS) const
Unsigned division operation.
Definition: APInt.cpp:1573
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:412
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition: BasicBlock.h:62
const Instruction & back() const
Definition: BasicBlock.h:484
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition: DenseMap.h:203
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:284
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:322
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Definition: Instructions.h:949
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2571
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
Definition: IRBuilder.h:547
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Definition: IRBuilder.h:2559
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
Definition: IRBuilder.h:2618
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Definition: IRBuilder.h:562
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Definition: IRBuilder.cpp:834
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition: IRBuilder.h:522
InstTy * Insert(InstTy *I, const Twine &Name="") const
Insert and return the specified instruction.
Definition: IRBuilder.h:172
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Definition: IRBuilder.h:207
Type * getVoidTy()
Fetch the type representing void.
Definition: IRBuilder.h:600
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2780
A wrapper class for inspecting calls to intrinsic functions.
Definition: IntrinsicInst.h:49
An instruction for reading from memory.
Definition: Instructions.h:180
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
Definition: PassManager.h:716
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Definition: Constants.cpp:1885
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition: Analysis.h:132
A vector that has set insertion semantics.
Definition: SetVector.h:59
void clear()
Completely clear the SetVector.
Definition: SetVector.h:284
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition: SetVector.h:168
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:401
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:541
bool empty() const
Definition: SmallVector.h:82
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
An instruction for storing to memory.
Definition: Instructions.h:296
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
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.
Definition: Type.cpp:414
Type * getTypeParameter(unsigned i) const
Definition: DerivedTypes.h:828
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition: Type.h:352
A Use represents the edge between a Value definition and its users.
Definition: Use.h:35
LLVM Value Representation.
Definition: Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:546
LLVM_ABI bool isTyped() const
TargetExtType * getHandleTy() const
Definition: DXILResource.h:303
dxil::ResourceKind getResourceKind() const
Definition: DXILResource.h:325
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
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...
Definition: STLExtras.h:663
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:428
FunctionPass * createDXILResourceAccessLegacyPass()
Pass to update resource accesses to use load/store directly.
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1669
@ RF_IgnoreMissingLocals
If this flag is set, the remapper ignores missing function-local entries (Argument,...
Definition: ValueMapper.h:98
@ RF_NoModuleLevelChanges
If this flag is set, the remapper knows that only local values within a function (such as an instruct...
Definition: ValueMapper.h:80
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr, const MetadataPredicate *IdentityMD=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM.
Definition: ValueMapper.h:289
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition: Error.cpp:180