LLVM 23.0.0git
SPIRVLegalizePointerCast.cpp
Go to the documentation of this file.
1//===-- SPIRVLegalizePointerCast.cpp ----------------------*- C++ -*-===//
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//
9// The LLVM IR has multiple legal patterns we cannot lower to Logical SPIR-V.
10// This pass modifies such loads to have an IR we can directly lower to valid
11// logical SPIR-V.
12// OpenCL can avoid this because they rely on ptrcast, which is not supported
13// by logical SPIR-V.
14//
15// This pass relies on the assign_ptr_type intrinsic to deduce the type of the
16// pointed values, must replace all occurences of `ptrcast`. This is why
17// unhandled cases are reported as unreachable: we MUST cover all cases.
18//
19// 1. Loading the first element of an array
20//
21// %array = [10 x i32]
22// %value = load i32, ptr %array
23//
24// LLVM can skip the GEP instruction, and only request loading the first 4
25// bytes. In logical SPIR-V, we need an OpAccessChain to access the first
26// element. This pass will add a getelementptr instruction before the load.
27//
28//
29// 2. Implicit downcast from load
30//
31// %1 = getelementptr <4 x i32>, ptr %vec4, i64 0
32// %2 = load <3 x i32>, ptr %1
33//
34// The pointer in the GEP instruction is only used for offset computations,
35// but it doesn't NEED to match the pointed type. OpAccessChain however
36// requires this. Also, LLVM loads define the bitwidth of the load, not the
37// pointer. In this example, we can guess %vec4 is a vec4 thanks to the GEP
38// instruction basetype, but we only want to load the first 3 elements, hence
39// do a partial load. In logical SPIR-V, this is not legal. What we must do
40// is load the full vector (basetype), extract 3 elements, and recombine them
41// to form a 3-element vector.
42//
43//===----------------------------------------------------------------------===//
44
45#include "SPIRV.h"
46#include "SPIRVSubtarget.h"
47#include "SPIRVTargetMachine.h"
48#include "SPIRVUtils.h"
49#include "llvm/IR/IRBuilder.h"
51#include "llvm/IR/Intrinsics.h"
52#include "llvm/IR/IntrinsicsSPIRV.h"
55
56using namespace llvm;
57
58namespace {
59class SPIRVLegalizePointerCast : public FunctionPass {
60
61 // Builds the `spv_assign_type` assigning |Ty| to |Value| at the current
62 // builder position.
63 void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg) {
64 Value *OfType = PoisonValue::get(Ty);
65 CallInst *AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type,
66 {Arg->getType()}, OfType, Arg, {}, B);
67 GR->addAssignPtrTypeInstr(Arg, AssignCI);
68 }
69
70 static FixedVectorType *makeVectorFromTotalBits(Type *ElemTy,
71 TypeSize TotalBits) {
72 unsigned ElemBits = ElemTy->getScalarSizeInBits();
73 assert(ElemBits && TotalBits % ElemBits == 0 &&
74 "TotalBits must be divisible by element bit size");
75 return FixedVectorType::get(ElemTy, TotalBits / ElemBits);
76 }
77
78 Value *resizeVectorBitsWithShuffle(IRBuilder<> &B, Value *V,
79 FixedVectorType *DstTy) {
80 auto *SrcTy = cast<FixedVectorType>(V->getType());
81 assert(SrcTy->getElementType() == DstTy->getElementType() &&
82 "shuffle resize expects identical element types");
83
84 const unsigned NumNeeded = DstTy->getNumElements();
85 const unsigned NumSource = SrcTy->getNumElements();
86
87 SmallVector<int> Mask(NumNeeded);
88 for (unsigned I = 0; I < NumNeeded; ++I)
89 Mask[I] = (I < NumSource) ? static_cast<int>(I) : -1;
90
91 Value *Resized = B.CreateShuffleVector(V, V, Mask);
92 buildAssignType(B, DstTy, Resized);
93 return Resized;
94 }
95
96 // Loads parts of the vector of type |SourceType| from the pointer |Source|
97 // and create a new vector of type |TargetType|. |TargetType| must be a vector
98 // type.
99 // Returns the loaded value.
100 Value *loadVectorFromVector(IRBuilder<> &B, FixedVectorType *SourceType,
101 FixedVectorType *TargetType, Value *Source) {
102 LoadInst *NewLoad = B.CreateLoad(SourceType, Source);
103 buildAssignType(B, SourceType, NewLoad);
104 Value *AssignValue = NewLoad;
105 if (TargetType->getElementType() != SourceType->getElementType()) {
106 const DataLayout &DL = B.GetInsertBlock()->getModule()->getDataLayout();
107 TypeSize TargetTypeSize = DL.getTypeSizeInBits(TargetType);
108 TypeSize SourceTypeSize = DL.getTypeSizeInBits(SourceType);
109
110 Value *BitcastSrcVal = NewLoad;
111 FixedVectorType *BitcastSrcTy =
112 cast<FixedVectorType>(BitcastSrcVal->getType());
113 FixedVectorType *BitcastDstTy = TargetType;
114
115 if (TargetTypeSize != SourceTypeSize) {
116 unsigned TargetElemBits =
117 TargetType->getElementType()->getScalarSizeInBits();
118 if (SourceTypeSize % TargetElemBits == 0) {
119 // No Resize needed. Same total bits as source, but use target element
120 // type.
121 BitcastDstTy = makeVectorFromTotalBits(TargetType->getElementType(),
122 SourceTypeSize);
123 } else {
124 // Resize source to target total bitwidth using source element type.
125 BitcastSrcTy = makeVectorFromTotalBits(SourceType->getElementType(),
126 TargetTypeSize);
127 BitcastSrcVal = resizeVectorBitsWithShuffle(B, NewLoad, BitcastSrcTy);
128 }
129 }
130 AssignValue =
131 B.CreateIntrinsic(Intrinsic::spv_bitcast,
132 {BitcastDstTy, BitcastSrcTy}, {BitcastSrcVal});
133 buildAssignType(B, BitcastDstTy, AssignValue);
134 if (BitcastDstTy == TargetType)
135 return AssignValue;
136 }
137
138 assert(TargetType->getNumElements() < SourceType->getNumElements());
139 SmallVector<int> Mask(/* Size= */ TargetType->getNumElements());
140 for (unsigned I = 0; I < TargetType->getNumElements(); ++I)
141 Mask[I] = I;
142 Value *Output = B.CreateShuffleVector(AssignValue, AssignValue, Mask);
143 buildAssignType(B, TargetType, Output);
144 return Output;
145 }
146
147 // Loads the first value in an aggregate pointed by |Source| of containing
148 // elements of type |ElementType|. Load flags will be copied from |BadLoad|,
149 // which should be the load being legalized. Returns the loaded value.
150 Value *loadFirstValueFromAggregate(IRBuilder<> &B, Type *ElementType,
151 Value *Source, LoadInst *BadLoad) {
153 Source->getType()};
154 SmallVector<Value *, 8> Args{/* isInBounds= */ B.getInt1(false), Source};
155
156 Type *AggregateType = GR->findDeducedElementType(Source);
157 assert(AggregateType && "Could not deduce aggregate type");
158 buildGEPIndexChain(B, ElementType, AggregateType, Args);
159
160 auto *GEP = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
161 GR->buildAssignPtr(B, ElementType, GEP);
162
163 LoadInst *LI = B.CreateLoad(ElementType, GEP);
164 LI->setAlignment(BadLoad->getAlign());
165 buildAssignType(B, ElementType, LI);
166 return LI;
167 }
168
169 // Loads elements from an array and constructs a vector.
170 Value *loadVectorFromArray(IRBuilder<> &B, FixedVectorType *TargetType,
171 Value *Source) {
172 // Load each element of the array.
173 SmallVector<Value *, 4> LoadedElements;
174 for (unsigned i = 0; i < TargetType->getNumElements(); ++i) {
175 // Create a GEP to access the i-th element of the array.
176 SmallVector<Type *, 2> Types = {Source->getType(), Source->getType()};
177 SmallVector<Value *, 4> Args;
178 Args.push_back(B.getInt1(false));
179 Args.push_back(Source);
180 Args.push_back(B.getInt32(0));
181 Args.push_back(ConstantInt::get(B.getInt32Ty(), i));
182 auto *ElementPtr = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
183 GR->buildAssignPtr(B, TargetType->getElementType(), ElementPtr);
184
185 // Load the value from the element pointer.
186 Value *Load = B.CreateLoad(TargetType->getElementType(), ElementPtr);
187 buildAssignType(B, TargetType->getElementType(), Load);
188 LoadedElements.push_back(Load);
189 }
190
191 // Build the vector from the loaded elements.
192 Value *NewVector = PoisonValue::get(TargetType);
193 buildAssignType(B, TargetType, NewVector);
194
195 for (unsigned i = 0; i < TargetType->getNumElements(); ++i) {
196 Value *Index = B.getInt32(i);
197 SmallVector<Type *, 4> Types = {TargetType, TargetType,
198 TargetType->getElementType(),
199 Index->getType()};
200 SmallVector<Value *> Args = {NewVector, LoadedElements[i], Index};
201 NewVector = B.CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args});
202 buildAssignType(B, TargetType, NewVector);
203 }
204 return NewVector;
205 }
206
207 // Stores elements from a vector into an array.
208 void storeArrayFromVector(IRBuilder<> &B, Value *SrcVector,
209 Value *DstArrayPtr, ArrayType *ArrTy,
210 Align Alignment) {
211 auto *VecTy = cast<FixedVectorType>(SrcVector->getType());
212
213 // Ensure the element types of the array and vector are the same.
214 assert(VecTy->getElementType() == ArrTy->getElementType() &&
215 "Element types of array and vector must be the same.");
216
217 const DataLayout &DL = B.GetInsertBlock()->getModule()->getDataLayout();
218 uint64_t ElemSize = DL.getTypeAllocSize(ArrTy->getElementType());
219
220 for (unsigned i = 0; i < VecTy->getNumElements(); ++i) {
221 // Create a GEP to access the i-th element of the array.
222 SmallVector<Type *, 2> Types = {DstArrayPtr->getType(),
223 DstArrayPtr->getType()};
224 SmallVector<Value *, 4> Args;
225 Args.push_back(B.getInt1(false));
226 Args.push_back(DstArrayPtr);
227 Args.push_back(B.getInt32(0));
228 Args.push_back(ConstantInt::get(B.getInt32Ty(), i));
229 auto *ElementPtr = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
230 GR->buildAssignPtr(B, ArrTy->getElementType(), ElementPtr);
231
232 // Extract the element from the vector and store it.
233 Value *Index = B.getInt32(i);
234 SmallVector<Type *, 3> EltTypes = {VecTy->getElementType(), VecTy,
235 Index->getType()};
236 SmallVector<Value *, 2> EltArgs = {SrcVector, Index};
237 Value *Element =
238 B.CreateIntrinsic(Intrinsic::spv_extractelt, {EltTypes}, {EltArgs});
239 buildAssignType(B, VecTy->getElementType(), Element);
240
241 Types = {Element->getType(), ElementPtr->getType()};
242 Align NewAlign = commonAlignment(Alignment, i * ElemSize);
243 Args = {Element, ElementPtr, B.getInt16(2), B.getInt32(NewAlign.value())};
244 B.CreateIntrinsic(Intrinsic::spv_store, {Types}, {Args});
245 }
246 }
247
248 // Replaces the load instruction to get rid of the ptrcast used as source
249 // operand.
250 void transformLoad(IRBuilder<> &B, LoadInst *LI, Value *CastedOperand,
251 Value *OriginalOperand) {
252 Type *FromTy = GR->findDeducedElementType(OriginalOperand);
253 Type *ToTy = GR->findDeducedElementType(CastedOperand);
254 Value *Output = nullptr;
255
256 auto *SAT = dyn_cast<ArrayType>(FromTy);
257 auto *SVT = dyn_cast<FixedVectorType>(FromTy);
258 auto *DVT = dyn_cast<FixedVectorType>(ToTy);
259
260 B.SetInsertPoint(LI);
261
262 // Destination is the element type of some member of FromTy. For example,
263 // loading the 1st element of an array:
264 // - float a = array[0];
265 if (isTypeFirstElementAggregate(ToTy, FromTy))
266 Output = loadFirstValueFromAggregate(B, ToTy, OriginalOperand, LI);
267 // Destination is a smaller vector than source or different vector type.
268 // - float3 v3 = vector4;
269 // - float4 v2 = int4;
270 else if (SVT && DVT)
271 Output = loadVectorFromVector(B, SVT, DVT, OriginalOperand);
272 else if (SAT && DVT && SAT->getElementType() == DVT->getElementType())
273 Output = loadVectorFromArray(B, DVT, OriginalOperand);
274 else
275 llvm_unreachable("Unimplemented implicit down-cast from load.");
276
277 GR->replaceAllUsesWith(LI, Output, /* DeleteOld= */ true);
278 DeadInstructions.push_back(LI);
279 }
280
281 // Creates an spv_insertelt instruction (equivalent to llvm's insertelement).
282 Value *makeInsertElement(IRBuilder<> &B, Value *Vector, Value *Element,
283 unsigned Index) {
284 Type *Int32Ty = Type::getInt32Ty(B.getContext());
285 SmallVector<Type *, 4> Types = {Vector->getType(), Vector->getType(),
286 Element->getType(), Int32Ty};
287 SmallVector<Value *> Args = {Vector, Element, B.getInt32(Index)};
288 Instruction *NewI =
289 B.CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args});
290 buildAssignType(B, Vector->getType(), NewI);
291 return NewI;
292 }
293
294 // Creates an spv_extractelt instruction (equivalent to llvm's
295 // extractelement).
296 Value *makeExtractElement(IRBuilder<> &B, Type *ElementType, Value *Vector,
297 unsigned Index) {
298 Type *Int32Ty = Type::getInt32Ty(B.getContext());
300 SmallVector<Value *> Args = {Vector, B.getInt32(Index)};
301 Instruction *NewI =
302 B.CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args});
303 buildAssignType(B, ElementType, NewI);
304 return NewI;
305 }
306
307 // Stores the given Src vector operand into the Dst vector, adjusting the size
308 // if required.
309 Value *storeVectorFromVector(IRBuilder<> &B, Value *Src, Value *Dst,
310 Align Alignment) {
311 FixedVectorType *SrcType = cast<FixedVectorType>(Src->getType());
312 FixedVectorType *DstType =
313 cast<FixedVectorType>(GR->findDeducedElementType(Dst));
314 auto dstNumElements = DstType->getNumElements();
315 auto srcNumElements = SrcType->getNumElements();
316
317 // if the element type differs, it is a bitcast.
318 if (DstType->getElementType() != SrcType->getElementType()) {
319 // Support bitcast between vectors of different sizes only if
320 // the total bitwidth is the same.
321 [[maybe_unused]] auto dstBitWidth =
322 DstType->getElementType()->getScalarSizeInBits() * dstNumElements;
323 [[maybe_unused]] auto srcBitWidth =
324 SrcType->getElementType()->getScalarSizeInBits() * srcNumElements;
325 assert(dstBitWidth == srcBitWidth &&
326 "Unsupported bitcast between vectors of different sizes.");
327
328 Src =
329 B.CreateIntrinsic(Intrinsic::spv_bitcast, {DstType, SrcType}, {Src});
330 buildAssignType(B, DstType, Src);
331 SrcType = DstType;
332
333 StoreInst *SI = B.CreateStore(Src, Dst);
334 SI->setAlignment(Alignment);
335 return SI;
336 }
337
338 assert(DstType->getNumElements() >= SrcType->getNumElements());
339 LoadInst *LI = B.CreateLoad(DstType, Dst);
340 LI->setAlignment(Alignment);
341 Value *OldValues = LI;
342 buildAssignType(B, OldValues->getType(), OldValues);
343 Value *NewValues = Src;
344
345 for (unsigned I = 0; I < SrcType->getNumElements(); ++I) {
346 Value *Element =
347 makeExtractElement(B, SrcType->getElementType(), NewValues, I);
348 OldValues = makeInsertElement(B, OldValues, Element, I);
349 }
350
351 StoreInst *SI = B.CreateStore(OldValues, Dst);
352 SI->setAlignment(Alignment);
353 return SI;
354 }
355
356 void buildGEPIndexChain(IRBuilder<> &B, Type *Search, Type *Aggregate,
357 SmallVectorImpl<Value *> &Indices) {
358 Indices.push_back(B.getInt32(0));
359
360 if (Search == Aggregate)
361 return;
362
363 if (auto *ST = dyn_cast<StructType>(Aggregate))
364 buildGEPIndexChain(B, Search, ST->getTypeAtIndex(0u), Indices);
365 else if (auto *AT = dyn_cast<ArrayType>(Aggregate))
366 buildGEPIndexChain(B, Search, AT->getElementType(), Indices);
367 else if (auto *VT = dyn_cast<FixedVectorType>(Aggregate))
368 buildGEPIndexChain(B, Search, VT->getElementType(), Indices);
369 else
370 llvm_unreachable("Bad access chain?");
371 }
372
373 // Stores the given Src value into the first entry of the Dst aggregate.
374 Value *storeToFirstValueAggregate(IRBuilder<> &B, Value *Src, Value *Dst,
375 Type *DstPointeeType, Align Alignment) {
376 SmallVector<Type *, 2> Types = {Dst->getType(), Dst->getType()};
377 SmallVector<Value *, 8> Args{/* isInBounds= */ B.getInt1(true), Dst};
378 buildGEPIndexChain(B, Src->getType(), DstPointeeType, Args);
379 auto *GEP = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
380 GR->buildAssignPtr(B, Src->getType(), GEP);
381 StoreInst *SI = B.CreateStore(Src, GEP);
382 SI->setAlignment(Alignment);
383 return SI;
384 }
385
386 bool isTypeFirstElementAggregate(Type *Search, Type *Aggregate) {
387 if (Search == Aggregate)
388 return true;
389 if (auto *ST = dyn_cast<StructType>(Aggregate))
390 return isTypeFirstElementAggregate(Search, ST->getTypeAtIndex(0u));
391 if (auto *VT = dyn_cast<FixedVectorType>(Aggregate))
392 return isTypeFirstElementAggregate(Search, VT->getElementType());
393 if (auto *AT = dyn_cast<ArrayType>(Aggregate))
394 return isTypeFirstElementAggregate(Search, AT->getElementType());
395 return false;
396 }
397
398 // Transforms a store instruction (or SPV intrinsic) using a ptrcast as
399 // operand into a valid logical SPIR-V store with no ptrcast.
400 void transformStore(IRBuilder<> &B, Instruction *BadStore, Value *Src,
401 Value *Dst, Align Alignment) {
402 Type *ToTy = GR->findDeducedElementType(Dst);
403 Type *FromTy = Src->getType();
404
405 auto *S_VT = dyn_cast<FixedVectorType>(FromTy);
406 auto *D_VT = dyn_cast<FixedVectorType>(ToTy);
407 auto *D_AT = dyn_cast<ArrayType>(ToTy);
408
409 B.SetInsertPoint(BadStore);
410 if (isTypeFirstElementAggregate(FromTy, ToTy))
411 storeToFirstValueAggregate(B, Src, Dst, ToTy, Alignment);
412 else if (D_VT && S_VT)
413 storeVectorFromVector(B, Src, Dst, Alignment);
414 else if (D_VT && !S_VT && FromTy == D_VT->getElementType())
415 storeToFirstValueAggregate(B, Src, Dst, D_VT, Alignment);
416 else if (D_AT && S_VT && S_VT->getElementType() == D_AT->getElementType())
417 storeArrayFromVector(B, Src, Dst, D_AT, Alignment);
418 else
419 llvm_unreachable("Unsupported ptrcast use in store. Please fix.");
420
421 DeadInstructions.push_back(BadStore);
422 }
423
424 void legalizePointerCast(IntrinsicInst *II) {
425 Value *CastedOperand = II;
426 Value *OriginalOperand = II->getOperand(0);
427
428 IRBuilder<> B(II->getContext());
429 std::vector<Value *> Users;
430 for (Use &U : II->uses())
431 Users.push_back(U.getUser());
432
433 for (Value *User : Users) {
434 if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
435 transformLoad(B, LI, CastedOperand, OriginalOperand);
436 continue;
437 }
438
439 if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
440 transformStore(B, SI, SI->getValueOperand(), OriginalOperand,
441 SI->getAlign());
442 continue;
443 }
444
445 if (IntrinsicInst *Intrin = dyn_cast<IntrinsicInst>(User)) {
446 if (Intrin->getIntrinsicID() == Intrinsic::spv_assign_ptr_type) {
447 DeadInstructions.push_back(Intrin);
448 continue;
449 }
450
451 if (Intrin->getIntrinsicID() == Intrinsic::spv_gep) {
452 GR->replaceAllUsesWith(CastedOperand, OriginalOperand,
453 /* DeleteOld= */ false);
454 continue;
455 }
456
457 if (Intrin->getIntrinsicID() == Intrinsic::spv_store) {
458 Align Alignment;
459 if (ConstantInt *C = dyn_cast<ConstantInt>(Intrin->getOperand(3)))
460 Alignment = Align(C->getZExtValue());
461 transformStore(B, Intrin, Intrin->getArgOperand(0), OriginalOperand,
462 Alignment);
463 continue;
464 }
465 }
466
467 llvm_unreachable("Unsupported ptrcast user. Please fix.");
468 }
469
470 DeadInstructions.push_back(II);
471 }
472
473public:
474 SPIRVLegalizePointerCast(SPIRVTargetMachine *TM) : FunctionPass(ID), TM(TM) {}
475
476 bool runOnFunction(Function &F) override {
477 const SPIRVSubtarget &ST = TM->getSubtarget<SPIRVSubtarget>(F);
478 GR = ST.getSPIRVGlobalRegistry();
479 DeadInstructions.clear();
480
481 std::vector<IntrinsicInst *> WorkList;
482 for (auto &BB : F) {
483 for (auto &I : BB) {
484 auto *II = dyn_cast<IntrinsicInst>(&I);
485 if (II && II->getIntrinsicID() == Intrinsic::spv_ptrcast)
486 WorkList.push_back(II);
487 }
488 }
489
490 for (IntrinsicInst *II : WorkList)
491 legalizePointerCast(II);
492
493 for (Instruction *I : DeadInstructions)
494 I->eraseFromParent();
495
496 return DeadInstructions.size() != 0;
497 }
498
499private:
500 SPIRVTargetMachine *TM = nullptr;
501 SPIRVGlobalRegistry *GR = nullptr;
502 std::vector<Instruction *> DeadInstructions;
503
504public:
505 static char ID;
506};
507} // namespace
508
509char SPIRVLegalizePointerCast::ID = 0;
510INITIALIZE_PASS(SPIRVLegalizePointerCast, "spirv-legalize-bitcast",
511 "SPIRV legalize bitcast pass", false, false)
512
514 return new SPIRVLegalizePointerCast(TM);
515}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool runOnFunction(Function &F, bool PostInlining)
Hexagon Common GEP
iv Induction Variable Users
Definition IVUsers.cpp:48
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
unsigned getNumElements() const
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Definition Type.cpp:802
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
void setAlignment(Align Align)
Type * getPointerOperandType() const
Align getAlign() const
Return the alignment of the access that is being performed.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
void push_back(const T &Elt)
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:230
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
Type * getElementType() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:68
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
Definition InstrProf.h:296
CallInst * buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef< Type * > Types, Value *Arg, Value *Arg2, ArrayRef< Constant * > Imms, IRBuilder<> &B)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Align commonAlignment(Align A, uint64_t Offset)
Returns the alignment that satisfies both alignments.
Definition Alignment.h:201
FunctionPass * createSPIRVLegalizePointerCastPass(SPIRVTargetMachine *TM)
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77