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
125 const DataLayout &DL = SI->getDataLayout();
126 IRBuilder<> Builder(SI);
127
128 Value *V = SI->getValueOperand();
129 assert(!V->getType()->isAggregateType() &&
130 "Resource store should be scalar or vector type");
131
132 Value *Index = II->getOperand(1);
133 // The offset for the rawbuffer load and store ops is always in bytes.
134 uint64_t AccessSize = 1;
135 Value *Offset =
136 traverseGEPOffsets(DL, Builder, SI->getPointerOperand(), AccessSize);
137
138 // For raw buffer (ie, HLSL's ByteAddressBuffer), we need to fold the access
139 // entirely into the index.
140 if (!RTI.isStruct()) {
141 auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
142 if (!ConstantOffset || !ConstantOffset->isZero())
143 Index = Builder.CreateAdd(Index, Offset);
144 Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
145 }
146
147 auto *Inst = Builder.CreateIntrinsic(Builder.getVoidTy(),
148 Intrinsic::dx_resource_store_rawbuffer,
149 {II->getOperand(0), Index, Offset, V});
150 SI->replaceAllUsesWith(Inst);
151}
152
184
187 const DataLayout &DL = LI->getDataLayout();
188 IRBuilder<> Builder(LI);
189 Type *ContainedType = RTI.getHandleTy()->getTypeParameter(0);
190 Type *LoadType = StructType::get(ContainedType, Builder.getInt1Ty());
191
192 Value *V =
193 Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_typedbuffer,
194 {II->getOperand(0), II->getOperand(1)});
195 V = Builder.CreateExtractValue(V, {0});
196
197 Type *ScalarType = ContainedType->getScalarType();
198 uint64_t AccessSize = DL.getTypeSizeInBits(ScalarType) / 8;
199 Value *Offset =
200 traverseGEPOffsets(DL, Builder, LI->getPointerOperand(), AccessSize);
201 auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
202 if (!ConstantOffset || !ConstantOffset->isZero())
203 V = Builder.CreateExtractElement(V, Offset);
204
205 // If we loaded a <1 x ...> instead of a scalar (presumably to feed a
206 // shufflevector), then make sure we're maintaining the resulting type.
207 if (auto *VT = dyn_cast<FixedVectorType>(LI->getType()))
208 if (VT->getNumElements() == 1 && !isa<FixedVectorType>(V->getType()))
209 V = Builder.CreateInsertElement(PoisonValue::get(VT), V,
210 Builder.getInt32(0));
211
212 LI->replaceAllUsesWith(V);
213}
214
217 const DataLayout &DL = LI->getDataLayout();
218 IRBuilder<> Builder(LI);
219
220 Type *LoadType = StructType::get(LI->getType(), Builder.getInt1Ty());
221 assert(!LI->getType()->isAggregateType() &&
222 "Resource load should be scalar or vector type");
223
224 Value *Index = II->getOperand(1);
225 // The offset for the rawbuffer load and store ops is always in bytes.
226 uint64_t AccessSize = 1;
227 Value *Offset =
228 traverseGEPOffsets(DL, Builder, LI->getPointerOperand(), AccessSize);
229
230 // For raw buffer (ie, HLSL's ByteAddressBuffer), we need to fold the access
231 // entirely into the index.
232 if (!RTI.isStruct()) {
233 auto *ConstantOffset = dyn_cast<ConstantInt>(Offset);
234 if (!ConstantOffset || !ConstantOffset->isZero())
235 Index = Builder.CreateAdd(Index, Offset);
236 Offset = llvm::PoisonValue::get(Builder.getInt32Ty());
237 }
238
239 Value *V =
240 Builder.CreateIntrinsic(LoadType, Intrinsic::dx_resource_load_rawbuffer,
241 {II->getOperand(0), Index, Offset});
242 V = Builder.CreateExtractValue(V, {0});
243
244 LI->replaceAllUsesWith(V);
245}
246
247namespace {
248/// Helper for building a `load.cbufferrow` intrinsic given a simple type.
249struct CBufferRowIntrin {
250 Intrinsic::ID IID;
251 Type *RetTy;
252 unsigned int EltSize;
253 unsigned int NumElts;
254
255 CBufferRowIntrin(const DataLayout &DL, Type *Ty) {
256 assert(Ty == Ty->getScalarType() && "Expected scalar type");
257
258 switch (DL.getTypeSizeInBits(Ty)) {
259 case 16:
260 IID = Intrinsic::dx_resource_load_cbufferrow_8;
261 RetTy = StructType::get(Ty, Ty, Ty, Ty, Ty, Ty, Ty, Ty);
262 EltSize = 2;
263 NumElts = 8;
264 break;
265 case 32:
266 IID = Intrinsic::dx_resource_load_cbufferrow_4;
267 RetTy = StructType::get(Ty, Ty, Ty, Ty);
268 EltSize = 4;
269 NumElts = 4;
270 break;
271 case 64:
272 IID = Intrinsic::dx_resource_load_cbufferrow_2;
273 RetTy = StructType::get(Ty, Ty);
274 EltSize = 8;
275 NumElts = 2;
276 break;
277 default:
278 llvm_unreachable("Only 16, 32, and 64 bit types supported");
279 }
280 }
281};
282} // namespace
283
286 const DataLayout &DL = LI->getDataLayout();
287
288 Type *Ty = LI->getType();
289 assert(!isa<StructType>(Ty) && "Structs not handled yet");
290 CBufferRowIntrin Intrin(DL, Ty->getScalarType());
291
292 StringRef Name = LI->getName();
293 Value *Handle = II->getOperand(0);
294
295 IRBuilder<> Builder(LI);
296
297 ConstantInt *GlobalOffset = dyn_cast<ConstantInt>(II->getOperand(1));
298 assert(GlobalOffset && "CBuffer getpointer index must be constant");
299
300 uint64_t GlobalOffsetVal = GlobalOffset->getZExtValue();
301 Value *CurrentRow = ConstantInt::get(
302 Builder.getInt32Ty(), GlobalOffsetVal / hlsl::CBufferRowSizeInBytes);
303 unsigned int CurrentIndex;
304
305 // Every object in a cbuffer either fits in a row or is aligned to a row. This
306 // means that only the very last pointer access can point into a row.
307 auto *LastGEP = dyn_cast<GEPOperator>(LI->getPointerOperand());
308 if (!LastGEP) {
309 // If we don't have a GEP at all we're just accessing the resource through
310 // the result of getpointer directly.
311 assert(LI->getPointerOperand() == II &&
312 "Unexpected indirect access to resource without GEP");
313 CurrentIndex =
314 (GlobalOffsetVal % hlsl::CBufferRowSizeInBytes) / Intrin.EltSize;
315 } else {
316 Value *GEPOffset = traverseGEPOffsets(
317 DL, Builder, LastGEP->getPointerOperand(), hlsl::CBufferRowSizeInBytes);
318 CurrentRow = Builder.CreateAdd(GEPOffset, CurrentRow);
319
320 APInt ConstantOffset(DL.getIndexTypeSizeInBits(LastGEP->getType()), 0);
321 if (LastGEP->accumulateConstantOffset(DL, ConstantOffset)) {
322 APInt Remainder(DL.getIndexTypeSizeInBits(LastGEP->getType()),
324 APInt::udivrem(ConstantOffset, Remainder, ConstantOffset, Remainder);
325 CurrentRow = Builder.CreateAdd(
326 CurrentRow, ConstantInt::get(Builder.getInt32Ty(), ConstantOffset));
327 CurrentIndex = Remainder.udiv(Intrin.EltSize).getZExtValue();
328 } else {
329 assert(LastGEP->getNumIndices() == 1 &&
330 "Last GEP of cbuffer access is not array or struct access");
331 // We assume a non-constant access will be row-aligned. This is safe
332 // because arrays and structs are always row aligned, and accesses to
333 // vector elements will show up as a load of the vector followed by an
334 // extractelement.
335 CurrentRow = cast<ConstantInt>(CurrentRow)->isZero()
336 ? *LastGEP->idx_begin()
337 : Builder.CreateAdd(CurrentRow, *LastGEP->idx_begin());
338 CurrentIndex = 0;
339 }
340 }
341
342 auto *CBufLoad = Builder.CreateIntrinsic(
343 Intrin.RetTy, Intrin.IID, {Handle, CurrentRow}, nullptr, Name + ".load");
344 auto *Elt =
345 Builder.CreateExtractValue(CBufLoad, {CurrentIndex++}, Name + ".extract");
346
347 // At this point we've loaded the first scalar of our result, but our original
348 // type may have been a vector.
349 unsigned int Remaining =
350 ((DL.getTypeSizeInBits(Ty) / 8) / Intrin.EltSize) - 1;
351 if (Remaining == 0) {
352 // We only have a single element, so we're done.
353 Value *Result = Elt;
354
355 // However, if we loaded a <1 x T>, then we need to adjust the type.
356 if (auto *VT = dyn_cast<FixedVectorType>(Ty)) {
357 assert(VT->getNumElements() == 1 && "Can't have multiple elements here");
358 Result = Builder.CreateInsertElement(PoisonValue::get(VT), Result,
359 Builder.getInt32(0), Name);
360 }
361 LI->replaceAllUsesWith(Result);
362 return;
363 }
364
365 // Walk each element and extract it, wrapping to new rows as needed.
366 SmallVector<Value *> Extracts{Elt};
367 while (Remaining--) {
368 CurrentIndex %= Intrin.NumElts;
369
370 if (CurrentIndex == 0) {
371 CurrentRow = Builder.CreateAdd(CurrentRow,
372 ConstantInt::get(Builder.getInt32Ty(), 1));
373 CBufLoad = Builder.CreateIntrinsic(Intrin.RetTy, Intrin.IID,
374 {Handle, CurrentRow}, nullptr,
375 Name + ".load");
376 }
377
378 Extracts.push_back(Builder.CreateExtractValue(CBufLoad, {CurrentIndex++},
379 Name + ".extract"));
380 }
381
382 // Finally, we build up the original loaded value.
383 Value *Result = PoisonValue::get(Ty);
384 for (int I = 0, E = Extracts.size(); I < E; ++I)
385 Result = Builder.CreateInsertElement(
386 Result, Extracts[I], Builder.getInt32(I), Name + formatv(".upto{}", I));
387 LI->replaceAllUsesWith(Result);
388}
389
422
427 auto *BB = Start->getParent();
428
429 // Seed with direct users in this block.
430 for (User *U : Start->users()) {
431 if (auto *I = dyn_cast<Instruction>(U)) {
432 if (I->getParent() == BB)
433 Worklist.push_back(I);
434 }
435 }
436
437 // BFS over transitive users, constrained to the same block.
438 while (!Worklist.empty()) {
439 Instruction *I = Worklist.pop_back_val();
440 if (!Visited.insert(I).second)
441 continue;
442 Out.push_back(I);
443
444 for (User *U : I->users()) {
445 if (auto *J = dyn_cast<Instruction>(U)) {
446 if (J->getParent() == BB)
447 Worklist.push_back(J);
448 }
449 }
450 for (Use &V : I->operands()) {
451 if (auto *J = dyn_cast<Instruction>(V)) {
452 if (J->getParent() == BB && V != Start)
453 Worklist.push_back(J);
454 }
455 }
456 }
457
458 // Order results in program order.
460 unsigned Idx = 0;
461 for (Instruction &I : *BB)
462 Ord[&I] = Idx++;
463
464 llvm::sort(Out, [&](Instruction *A, Instruction *B) {
465 return Ord.lookup(A) < Ord.lookup(B);
466 });
467
468 return Out;
469}
470
472 IRBuilder<> &Builder,
473 SmallVector<Instruction *> &UsesInBlock) {
474
476 Value *Val = Phi->getIncomingValueForBlock(BB);
477 VMap[Phi] = Val;
478 Builder.SetInsertPoint(&BB->back());
479 for (Instruction *I : UsesInBlock) {
480 // don't clone over the Phi just remap them
481 if (auto *PhiNested = dyn_cast<PHINode>(I)) {
482 VMap[PhiNested] = PhiNested->getIncomingValueForBlock(BB);
483 continue;
484 }
485 Instruction *Clone = I->clone();
486 RemapInstruction(Clone, VMap,
488 Builder.Insert(Clone);
489 VMap[I] = Clone;
490 }
491}
492
494 SmallVectorImpl<Instruction *> &PrevBBDeadInsts,
495 SetVector<BasicBlock *> &DeadBB) {
496 SmallVector<Instruction *> CurrBBDeadInsts;
497 for (User *U : II->users()) {
498 auto *Phi = dyn_cast<PHINode>(U);
499 if (!Phi)
500 continue;
501
502 IRBuilder<> Builder(Phi);
504 bool HasReturnUse = isa<ReturnInst>(UsesInBlock.back());
505
506 for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; I++) {
507 auto *CurrIncomingBB = Phi->getIncomingBlock(I);
508 phiNodeRemapHelper(Phi, CurrIncomingBB, Builder, UsesInBlock);
509 if (HasReturnUse)
510 PrevBBDeadInsts.push_back(&CurrIncomingBB->back());
511 }
512
513 CurrBBDeadInsts.push_back(Phi);
514
515 for (Instruction *I : UsesInBlock) {
516 CurrBBDeadInsts.push_back(I);
517 }
518 if (HasReturnUse) {
519 BasicBlock *PhiBB = Phi->getParent();
520 DeadBB.insert(PhiBB);
521 }
522 }
523 // Traverse the now-dead instructions in RPO and remove them.
524 for (Instruction *Dead : llvm::reverse(CurrBBDeadInsts))
525 Dead->eraseFromParent();
526 CurrBBDeadInsts.clear();
527}
528
530 SmallVector<User *> Worklist;
531 for (User *U : II->users())
532 Worklist.push_back(U);
533
535 while (!Worklist.empty()) {
536 User *U = Worklist.back();
537 Worklist.pop_back();
538
539 if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) {
540 for (User *U : GEP->users())
541 Worklist.push_back(U);
542 DeadInsts.push_back(GEP);
543
544 } else if (auto *SI = dyn_cast<StoreInst>(U)) {
545 assert(SI->getValueOperand() != II && "Pointer escaped!");
547 DeadInsts.push_back(SI);
548
549 } else if (auto *LI = dyn_cast<LoadInst>(U)) {
550 createLoadIntrinsic(II, LI, RTI);
551 DeadInsts.push_back(LI);
552 } else
553 llvm_unreachable("Unhandled instruction - pointer escaped?");
554 }
555
556 // Traverse the now-dead instructions in RPO and remove them.
557 for (Instruction *Dead : llvm::reverse(DeadInsts))
558 Dead->eraseFromParent();
559 II->eraseFromParent();
560}
561
565 SmallVector<Instruction *> PrevBBDeadInsts;
566 for (BasicBlock &BB : make_early_inc_range(F)) {
568 if (auto *II = dyn_cast<IntrinsicInst>(&I))
569 if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
570 phiNodeReplacement(II, PrevBBDeadInsts, DeadBB);
571
572 for (Instruction &I : BB)
573 if (auto *II = dyn_cast<IntrinsicInst>(&I))
574 if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
575 auto *HandleTy = cast<TargetExtType>(II->getArgOperand(0)->getType());
576 Resources.emplace_back(II, DRTM[HandleTy]);
577 }
578 }
579 for (auto *Dead : PrevBBDeadInsts)
580 Dead->eraseFromParent();
581 PrevBBDeadInsts.clear();
582 for (auto *Dead : DeadBB)
583 Dead->eraseFromParent();
584 DeadBB.clear();
585
586 for (auto &[II, RI] : Resources)
587 replaceAccess(II, RI);
588
589 return !Resources.empty();
590}
591
594 auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
595 DXILResourceTypeMap *DRTM =
596 MAMProxy.getCachedResult<DXILResourceTypeAnalysis>(*F.getParent());
597 assert(DRTM && "DXILResourceTypeAnalysis must be available");
598
599 bool MadeChanges = transformResourcePointers(F, *DRTM);
600 if (!MadeChanges)
601 return PreservedAnalyses::all();
602
606 return PA;
607}
608
609namespace {
610class DXILResourceAccessLegacy : public FunctionPass {
611public:
612 bool runOnFunction(Function &F) override {
613 DXILResourceTypeMap &DRTM =
614 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
615 return transformResourcePointers(F, DRTM);
616 }
617 StringRef getPassName() const override { return "DXIL Resource Access"; }
618 DXILResourceAccessLegacy() : FunctionPass(ID) {}
619
620 static char ID; // Pass identification.
621 void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
622 AU.addRequired<DXILResourceTypeWrapperPass>();
623 AU.addPreserved<DominatorTreeWrapperPass>();
624 }
625};
626char DXILResourceAccessLegacy::ID = 0;
627} // end anonymous namespace
628
629INITIALIZE_PASS_BEGIN(DXILResourceAccessLegacy, DEBUG_TYPE,
630 "DXIL Resource Access", false, false)
632INITIALIZE_PASS_END(DXILResourceAccessLegacy, DEBUG_TYPE,
633 "DXIL Resource Access", false, false)
634
636 return new DXILResourceAccessLegacy();
637}
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, dxil::ResourceTypeInfo &RTI)
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 void createRawLoad(IntrinsicInst *II, LoadInst *LI, dxil::ResourceTypeInfo &RTI)
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 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
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:304
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:553
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
TargetExtType * getHandleTy() const
LLVM_ABI bool isStruct() 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