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"
14#include "llvm/IR/BasicBlock.h"
15#include "llvm/IR/Dominators.h"
16#include "llvm/IR/IRBuilder.h"
17#include "llvm/IR/Instruction.h"
20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/IntrinsicsDirectX.h"
22#include "llvm/IR/User.h"
26
27#define DEBUG_TYPE "dxil-resource-access"
28
29using namespace llvm;
30
32 Value *Ptr, uint64_t AccessSize) {
33 Value *Offset = nullptr;
34
35 while (Ptr) {
36 if (auto *II = dyn_cast<IntrinsicInst>(Ptr)) {
37 assert(II->getIntrinsicID() == Intrinsic::dx_resource_getpointer &&
38 "Resource access through unexpected intrinsic");
39 return Offset ? Offset : ConstantInt::get(Builder.getInt32Ty(), 0);
40 }
41
43 assert(GEP && "Resource access through unexpected instruction");
44
45 unsigned NumIndices = GEP->getNumIndices();
46 uint64_t IndexScale = DL.getTypeAllocSize(GEP->getSourceElementType());
47 APInt ConstantOffset(DL.getIndexTypeSizeInBits(GEP->getType()), 0);
48 Value *GEPOffset;
49 if (GEP->accumulateConstantOffset(DL, ConstantOffset)) {
50 // We have a constant offset (in bytes).
51 GEPOffset =
52 ConstantInt::get(DL.getIndexType(GEP->getType()), ConstantOffset);
53 IndexScale = 1;
54 } else if (NumIndices == 1) {
55 // If we have a single index we're indexing into a top level array. This
56 // generally only happens with cbuffers.
57 GEPOffset = *GEP->idx_begin();
58 } else if (NumIndices == 2) {
59 // If we have two indices, this should be an access through a pointer.
60 auto IndexIt = GEP->idx_begin();
61 assert(cast<ConstantInt>(IndexIt)->getZExtValue() == 0 &&
62 "GEP is not indexing through pointer");
63 GEPOffset = *(++IndexIt);
64 } else
65 llvm_unreachable("Unhandled GEP structure for resource access");
66
67 uint64_t ElemSize = AccessSize;
68 if (!(IndexScale % ElemSize)) {
69 // If our scale is an exact multiple of the access size, adjust the
70 // scaling to avoid an unnecessary division.
71 IndexScale /= ElemSize;
72 ElemSize = 1;
73 }
74 if (IndexScale != 1)
75 GEPOffset = Builder.CreateMul(
76 GEPOffset, ConstantInt::get(Builder.getInt32Ty(), IndexScale));
77 if (ElemSize != 1)
78 GEPOffset = Builder.CreateUDiv(
79 GEPOffset, ConstantInt::get(Builder.getInt32Ty(), ElemSize));
80
81 Offset = Offset ? Builder.CreateAdd(Offset, GEPOffset) : GEPOffset;
82 Ptr = GEP->getPointerOperand();
83 }
84
85 llvm_unreachable("GEP of null pointer?");
86}
87
90 const DataLayout &DL = SI->getDataLayout();
91 IRBuilder<> Builder(SI);
92 Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
93 Type *ScalarType = ContainedType->getScalarType();
94 Type *LoadType = StructType::get(ContainedType, Builder.getInt1Ty());
95
96 Value *V = SI->getValueOperand();
97 if (V->getType() == ContainedType) {
98 // V is already the right type.
99 assert(SI->getPointerOperand() == II &&
100 "Store of whole element has mismatched address to store to");
101 } else if (V->getType() == ScalarType) {
102 // We're storing a scalar, so we need to load the current value and only
103 // replace the relevant part.
104 auto *Load = Builder.CreateIntrinsic(
105 LoadType, Intrinsic::dx_resource_load_typedbuffer,
106 {II->getOperand(0), II->getOperand(1)});
107 auto *Struct = Builder.CreateExtractValue(Load, {0});
108
109 uint64_t AccessSize = DL.getTypeSizeInBits(ScalarType) / 8;
110 Value *Offset =
111 traverseGEPOffsets(DL, Builder, SI->getPointerOperand(), AccessSize);
112 V = Builder.CreateInsertElement(Struct, V, Offset);
113 } else {
114 llvm_unreachable("Store to typed resource has invalid type");
115 }
116
117 auto *Inst = Builder.CreateIntrinsic(
118 Builder.getVoidTy(), Intrinsic::dx_resource_store_typedbuffer,
119 {II->getOperand(0), II->getOperand(1), V});
120 SI->replaceAllUsesWith(Inst);
121}
122
124 const DataLayout &DL = SI->getDataLayout();
125 IRBuilder<> Builder(SI);
126
127 Value *V = SI->getValueOperand();
128 // The offset for the rawbuffer load and store ops is always in bytes.
129 uint64_t AccessSize = 1;
130 Value *Offset =
131 traverseGEPOffsets(DL, Builder, SI->getPointerOperand(), AccessSize);
132 // TODO: break up larger types
133 auto *Inst = Builder.CreateIntrinsic(
134 Builder.getVoidTy(), Intrinsic::dx_resource_store_rawbuffer,
135 {II->getOperand(0), II->getOperand(1), Offset, V});
136 SI->replaceAllUsesWith(Inst);
137}
138
170
173 const DataLayout &DL = LI->getDataLayout();
174 IRBuilder<> Builder(LI);
175 Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
176 Type *LoadType = StructType::get(ContainedType, Builder.getInt1Ty());
177
178 Value *V =
179 Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_typedbuffer,
180 {II->getOperand(0), II->getOperand(1)});
181 V = Builder.CreateExtractValue(V, {0});
182
183 Type *ScalarType = ContainedType->getScalarType();
184 uint64_t AccessSize = DL.getTypeSizeInBits(ScalarType) / 8;
185 Value *Offset =
186 traverseGEPOffsets(DL, Builder, LI->getPointerOperand(), AccessSize);
187 auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
188 if (!ConstantOffset || !ConstantOffset->isZero())
189 V = Builder.CreateExtractElement(V, Offset);
190
191 // If we loaded a <1 x ...> instead of a scalar (presumably to feed a
192 // shufflevector), then make sure we're maintaining the resulting type.
193 if (auto *VT = dyn_cast<FixedVectorType>(LI->getType()))
194 if (VT->getNumElements() == 1 && !isa<FixedVectorType>(V->getType()))
195 V = Builder.CreateInsertElement(PoisonValue::get(VT), V,
196 Builder.getInt32(0));
197
198 LI->replaceAllUsesWith(V);
199}
200
202 const DataLayout &DL = LI->getDataLayout();
203 IRBuilder<> Builder(LI);
204
205 // TODO: break up larger types
206 Type *LoadType = StructType::get(LI->getType(), Builder.getInt1Ty());
207
208 // The offset for the rawbuffer load and store ops is always in bytes.
209 uint64_t AccessSize = 1;
210 Value *Offset =
211 traverseGEPOffsets(DL, Builder, LI->getPointerOperand(), AccessSize);
212 Value *V =
213 Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_rawbuffer,
214 {II->getOperand(0), II->getOperand(1), Offset});
215 V = Builder.CreateExtractValue(V, {0});
216
217 LI->replaceAllUsesWith(V);
218}
219
220namespace {
221/// Helper for building a `load.cbufferrow` intrinsic given a simple type.
222struct CBufferRowIntrin {
223 Intrinsic::ID IID;
224 Type *RetTy;
225 unsigned int EltSize;
226 unsigned int NumElts;
227
228 CBufferRowIntrin(const DataLayout &DL, Type *Ty) {
229 assert(Ty == Ty->getScalarType() && "Expected scalar type");
230
231 switch (DL.getTypeSizeInBits(Ty)) {
232 case 16:
233 IID = Intrinsic::dx_resource_load_cbufferrow_8;
234 RetTy = StructType::get(Ty, Ty, Ty, Ty, Ty, Ty, Ty, Ty);
235 EltSize = 2;
236 NumElts = 8;
237 break;
238 case 32:
239 IID = Intrinsic::dx_resource_load_cbufferrow_4;
240 RetTy = StructType::get(Ty, Ty, Ty, Ty);
241 EltSize = 4;
242 NumElts = 4;
243 break;
244 case 64:
245 IID = Intrinsic::dx_resource_load_cbufferrow_2;
246 RetTy = StructType::get(Ty, Ty);
247 EltSize = 8;
248 NumElts = 2;
249 break;
250 default:
251 llvm_unreachable("Only 16, 32, and 64 bit types supported");
252 }
253 }
254};
255} // namespace
256
259 const DataLayout &DL = LI->getDataLayout();
260
261 Type *Ty = LI->getType();
262 assert(!isa<StructType>(Ty) && "Structs not handled yet");
263 CBufferRowIntrin Intrin(DL, Ty->getScalarType());
264
265 StringRef Name = LI->getName();
266 Value *Handle = II->getOperand(0);
267
268 IRBuilder<> Builder(LI);
269
270 ConstantInt *GlobalOffset = dyn_cast<ConstantInt>(II->getOperand(1));
271 assert(GlobalOffset && "CBuffer getpointer index must be constant");
272
273 uint64_t GlobalOffsetVal = GlobalOffset->getZExtValue();
274 Value *CurrentRow = ConstantInt::get(
275 Builder.getInt32Ty(), GlobalOffsetVal / hlsl::CBufferRowSizeInBytes);
276 unsigned int CurrentIndex;
277
278 // Every object in a cbuffer either fits in a row or is aligned to a row. This
279 // means that only the very last pointer access can point into a row.
280 auto *LastGEP = dyn_cast<GEPOperator>(LI->getPointerOperand());
281 if (!LastGEP) {
282 // If we don't have a GEP at all we're just accessing the resource through
283 // the result of getpointer directly.
284 assert(LI->getPointerOperand() == II &&
285 "Unexpected indirect access to resource without GEP");
286 CurrentIndex =
287 (GlobalOffsetVal % hlsl::CBufferRowSizeInBytes) / Intrin.EltSize;
288 } else {
289 Value *GEPOffset = traverseGEPOffsets(
290 DL, Builder, LastGEP->getPointerOperand(), hlsl::CBufferRowSizeInBytes);
291 CurrentRow = Builder.CreateAdd(GEPOffset, CurrentRow);
292
293 APInt ConstantOffset(DL.getIndexTypeSizeInBits(LastGEP->getType()), 0);
294 if (LastGEP->accumulateConstantOffset(DL, ConstantOffset)) {
295 APInt Remainder(DL.getIndexTypeSizeInBits(LastGEP->getType()),
297 APInt::udivrem(ConstantOffset, Remainder, ConstantOffset, Remainder);
298 CurrentRow = Builder.CreateAdd(
299 CurrentRow, ConstantInt::get(Builder.getInt32Ty(), ConstantOffset));
300 CurrentIndex = Remainder.udiv(Intrin.EltSize).getZExtValue();
301 } else {
302 assert(LastGEP->getNumIndices() == 1 &&
303 "Last GEP of cbuffer access is not array or struct access");
304 // We assume a non-constant access will be row-aligned. This is safe
305 // because arrays and structs are always row aligned, and accesses to
306 // vector elements will show up as a load of the vector followed by an
307 // extractelement.
308 CurrentRow = cast<ConstantInt>(CurrentRow)->isZero()
309 ? *LastGEP->idx_begin()
310 : Builder.CreateAdd(CurrentRow, *LastGEP->idx_begin());
311 CurrentIndex = 0;
312 }
313 }
314
315 auto *CBufLoad = Builder.CreateIntrinsic(
316 Intrin.RetTy, Intrin.IID, {Handle, CurrentRow}, nullptr, Name + ".load");
317 auto *Elt =
318 Builder.CreateExtractValue(CBufLoad, {CurrentIndex++}, Name + ".extract");
319
320 // At this point we've loaded the first scalar of our result, but our original
321 // type may have been a vector.
322 unsigned int Remaining =
323 ((DL.getTypeSizeInBits(Ty) / 8) / Intrin.EltSize) - 1;
324 if (Remaining == 0) {
325 // We only have a single element, so we're done.
326 Value *Result = Elt;
327
328 // However, if we loaded a <1 x T>, then we need to adjust the type.
329 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
330 assert(VT->getNumElements() == 1 && "Can't have multiple elements here");
331 Result = Builder.CreateInsertElement(PoisonValue::get(VT), Result,
332 Builder.getInt32(0), Name);
333 }
334 LI->replaceAllUsesWith(Result);
335 return;
336 }
337
338 // Walk each element and extract it, wrapping to new rows as needed.
339 SmallVector<Value *> Extracts{Elt};
340 while (Remaining--) {
341 CurrentIndex %= Intrin.NumElts;
342
343 if (CurrentIndex == 0) {
344 CurrentRow = Builder.CreateAdd(CurrentRow,
345 ConstantInt::get(Builder.getInt32Ty(), 1));
346 CBufLoad = Builder.CreateIntrinsic(Intrin.RetTy, Intrin.IID,
347 {Handle, CurrentRow}, nullptr,
348 Name + ".load");
349 }
350
351 Extracts.push_back(Builder.CreateExtractValue(CBufLoad, {CurrentIndex++},
352 Name + ".extract"));
353 }
354
355 // Finally, we build up the original loaded value.
356 Value *Result = PoisonValue::get(Ty);
357 for (int I = 0, E = Extracts.size(); I < E; ++I)
358 Result = Builder.CreateInsertElement(
359 Result, Extracts[I], Builder.getInt32(I), Name + formatv(".upto{}", I));
360 LI->replaceAllUsesWith(Result);
361}
362
395
400 auto *BB = Start->getParent();
401
402 // Seed with direct users in this block.
403 for (User *U : Start->users()) {
404 if (auto *I = dyn_cast<Instruction>(U)) {
405 if (I->getParent() == BB)
406 Worklist.push_back(I);
407 }
408 }
409
410 // BFS over transitive users, constrained to the same block.
411 while (!Worklist.empty()) {
412 Instruction *I = Worklist.pop_back_val();
413 if (!Visited.insert(I).second)
414 continue;
415 Out.push_back(I);
416
417 for (User *U : I->users()) {
418 if (auto *J = dyn_cast<Instruction>(U)) {
419 if (J->getParent() == BB)
420 Worklist.push_back(J);
421 }
422 }
423 for (Use &V : I->operands()) {
424 if (auto *J = dyn_cast<Instruction>(V)) {
425 if (J->getParent() == BB && V != Start)
426 Worklist.push_back(J);
427 }
428 }
429 }
430
431 // Order results in program order.
433 unsigned Idx = 0;
434 for (Instruction &I : *BB)
435 Ord[&I] = Idx++;
436
437 llvm::sort(Out, [&](Instruction *A, Instruction *B) {
438 return Ord.lookup(A) < Ord.lookup(B);
439 });
440
441 return Out;
442}
443
445 IRBuilder<> &Builder,
446 SmallVector<Instruction *> &UsesInBlock) {
447
449 Value *Val = Phi->getIncomingValueForBlock(BB);
450 VMap[Phi] = Val;
451 Builder.SetInsertPoint(&BB->back());
452 for (Instruction *I : UsesInBlock) {
453 // don't clone over the Phi just remap them
454 if (auto *PhiNested = dyn_cast<PHINode>(I)) {
455 VMap[PhiNested] = PhiNested->getIncomingValueForBlock(BB);
456 continue;
457 }
458 Instruction *Clone = I->clone();
459 RemapInstruction(Clone, VMap,
461 Builder.Insert(Clone);
462 VMap[I] = Clone;
463 }
464}
465
467 SmallVectorImpl<Instruction *> &PrevBBDeadInsts,
468 SetVector<BasicBlock *> &DeadBB) {
469 SmallVector<Instruction *> CurrBBDeadInsts;
470 for (User *U : II->users()) {
471 auto *Phi = dyn_cast<PHINode>(U);
472 if (!Phi)
473 continue;
474
475 IRBuilder<> Builder(Phi);
477 bool HasReturnUse = isa<ReturnInst>(UsesInBlock.back());
478
479 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; I++) {
480 auto *CurrIncomingBB = Phi->getIncomingBlock(I);
481 phiNodeRemapHelper(Phi, CurrIncomingBB, Builder, UsesInBlock);
482 if (HasReturnUse)
483 PrevBBDeadInsts.push_back(&CurrIncomingBB->back());
484 }
485
486 CurrBBDeadInsts.push_back(Phi);
487
488 for (Instruction *I : UsesInBlock) {
489 CurrBBDeadInsts.push_back(I);
490 }
491 if (HasReturnUse) {
492 BasicBlock *PhiBB = Phi->getParent();
493 DeadBB.insert(PhiBB);
494 }
495 }
496 // Traverse the now-dead instructions in RPO and remove them.
497 for (Instruction *Dead : llvm::reverse(CurrBBDeadInsts))
498 Dead->eraseFromParent();
499 CurrBBDeadInsts.clear();
500}
501
503 SmallVector<User *> Worklist;
504 for (User *U : II->users())
505 Worklist.push_back(U);
506
508 while (!Worklist.empty()) {
509 User *U = Worklist.back();
510 Worklist.pop_back();
511
512 if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) {
513 for (User *U : GEP->users())
514 Worklist.push_back(U);
515 DeadInsts.push_back(GEP);
516
517 } else if (auto *SI = dyn_cast<StoreInst>(U)) {
518 assert(SI->getValueOperand() != II && "Pointer escaped!");
520 DeadInsts.push_back(SI);
521
522 } else if (auto *LI = dyn_cast<LoadInst>(U)) {
523 createLoadIntrinsic(II, LI, RTI);
524 DeadInsts.push_back(LI);
525 } else
526 llvm_unreachable("Unhandled instruction - pointer escaped?");
527 }
528
529 // Traverse the now-dead instructions in RPO and remove them.
530 for (Instruction *Dead : llvm::reverse(DeadInsts))
531 Dead->eraseFromParent();
532 II->eraseFromParent();
533}
534
538 SmallVector<Instruction *> PrevBBDeadInsts;
539 for (BasicBlock &BB : make_early_inc_range(F)) {
541 if (auto *II = dyn_cast<IntrinsicInst>(&I))
542 if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
543 phiNodeReplacement(II, PrevBBDeadInsts, DeadBB);
544
545 for (Instruction &I : BB)
546 if (auto *II = dyn_cast<IntrinsicInst>(&I))
547 if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
548 auto *HandleTy = cast<TargetExtType>(II->getArgOperand(0)->getType());
549 Resources.emplace_back(II, DRTM[HandleTy]);
550 }
551 }
552 for (auto *Dead : PrevBBDeadInsts)
553 Dead->eraseFromParent();
554 PrevBBDeadInsts.clear();
555 for (auto *Dead : DeadBB)
556 Dead->eraseFromParent();
557 DeadBB.clear();
558
559 for (auto &[II, RI] : Resources)
560 replaceAccess(II, RI);
561
562 return !Resources.empty();
563}
564
567 auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
568 DXILResourceTypeMap *DRTM =
569 MAMProxy.getCachedResult<DXILResourceTypeAnalysis>(*F.getParent());
570 assert(DRTM && "DXILResourceTypeAnalysis must be available");
571
572 bool MadeChanges = transformResourcePointers(F, *DRTM);
573 if (!MadeChanges)
574 return PreservedAnalyses::all();
575
579 return PA;
580}
581
582namespace {
583class DXILResourceAccessLegacy : public FunctionPass {
584public:
585 bool runOnFunction(Function &F) override {
586 DXILResourceTypeMap &DRTM =
587 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
588 return transformResourcePointers(F, DRTM);
589 }
590 StringRef getPassName() const override { return "DXIL Resource Access"; }
591 DXILResourceAccessLegacy() : FunctionPass(ID) {}
592
593 static char ID; // Pass identification.
594 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
595 AU.addRequired<DXILResourceTypeWrapperPass>();
596 AU.addPreserved<DominatorTreeWrapperPass>();
597 }
598};
599char DXILResourceAccessLegacy::ID = 0;
600} // end anonymous namespace
601
602INITIALIZE_PASS_BEGIN(DXILResourceAccessLegacy, DEBUG_TYPE,
603 "DXIL Resource Access", false, false)
605INITIALIZE_PASS_END(DXILResourceAccessLegacy, DEBUG_TYPE,
606 "DXIL Resource Access", false, false)
607
609 return new DXILResourceAccessLegacy();
610}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static void phiNodeRemapHelper(PHINode *Phi, BasicBlock *BB, IRBuilder<> &Builder, SmallVector< Instruction * > &UsesInBlock)
static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createRawStore(IntrinsicInst *II, StoreInst *SI)
static void createTypedBufferLoad(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createTypedBufferStore(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
static bool transformResourcePointers(Function &F, DXILResourceTypeMap &DRTM)
static Value * traverseGEPOffsets(const DataLayout &DL, IRBuilder<> &Builder, Value *Ptr, uint64_t AccessSize)
static void createStoreIntrinsic(IntrinsicInst *II, StoreInst *SI, dxil::ResourceTypeInfo &RTI)
static void createCBufferLoad(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
static void createRawLoad(IntrinsicInst *II, LoadInst *LI)
static SmallVector< Instruction * > collectBlockUseDef(Instruction *Start)
static void phiNodeReplacement(IntrinsicInst *II, SmallVectorImpl< Instruction * > &PrevBBDeadInsts, SetVector< BasicBlock * > &DeadBB)
static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI)
static bool runOnFunction(Function &F, bool PostInlining)
#define DEBUG_TYPE
Hexagon Common GEP
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
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.
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt udiv(const APInt &RHS) const
Unsigned division operation.
Definition APInt.cpp:1573
static LLVM_ABI void udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder)
Dual division/remainder interface.
Definition APInt.cpp:1758
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1541
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
This is the shared class of boolean and integer constants.
Definition Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:171
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
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:205
Analysis pass which computes a DominatorTree.
Definition Dominators.h:283
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2788
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.
An instruction for reading from memory.
Value * getPointerOperand()
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.
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:57
void clear()
Completely clear the SetVector.
Definition SetVector.h:267
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:151
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
An instruction for storing to memory.
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:413
Type * getTypeParameter(unsigned i) const
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:352
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:293
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 StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
TargetExtType * getHandleTy() const
dxil::ResourceKind getResourceKind() const
#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
const unsigned CBufferRowSizeInBytes
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
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:632
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
auto reverse(ContainerTy &&C)
Definition STLExtras.h:406
FunctionPass * createDXILResourceAccessLegacyPass()
Pass to update resource accesses to use load/store directly.
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1634
@ 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
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...
Definition Casting.h:547
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.
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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.
Definition Error.cpp:180