52#include "llvm/IR/IntrinsicsSPIRV.h"
66 {Arg->
getType()}, OfType, Arg, {},
B);
67 GR->addAssignPtrTypeInstr(Arg, AssignCI);
75 FixedVectorType *TargetType,
Value *Source) {
76 LoadInst *NewLoad =
B.CreateLoad(SourceType, Source);
77 buildAssignType(
B, SourceType, NewLoad);
78 Value *AssignValue = NewLoad;
80 const DataLayout &
DL =
B.GetInsertBlock()->getModule()->getDataLayout();
81 [[maybe_unused]] TypeSize TargetTypeSize =
82 DL.getTypeSizeInBits(TargetType);
83 [[maybe_unused]] TypeSize SourceTypeSize =
84 DL.getTypeSizeInBits(SourceType);
85 assert(TargetTypeSize == SourceTypeSize);
86 AssignValue =
B.CreateIntrinsic(Intrinsic::spv_bitcast,
87 {TargetType, SourceType}, {NewLoad});
88 buildAssignType(
B, TargetType, AssignValue);
96 Value *Output =
B.CreateShuffleVector(AssignValue, AssignValue, Mask);
97 buildAssignType(
B, TargetType, Output);
105 Value *Source, LoadInst *BadLoad) {
109 B.getInt32(0),
B.getInt32(0)};
110 auto *
GEP =
B.CreateIntrinsic(Intrinsic::spv_gep, {
Types}, {
Args});
111 GR->buildAssignPtr(
B, ElementType,
GEP);
113 LoadInst *LI =
B.CreateLoad(ElementType,
GEP);
115 buildAssignType(
B, ElementType, LI);
122 Value *OriginalOperand) {
123 Type *FromTy = GR->findDeducedElementType(OriginalOperand);
124 Type *ToTy = GR->findDeducedElementType(CastedOperand);
125 Value *Output =
nullptr;
132 B.SetInsertPoint(LI);
137 if (
SAT &&
SAT->getElementType() == ToTy)
138 Output = loadFirstValueFromAggregate(
B,
SAT->getElementType(),
139 OriginalOperand, LI);
143 else if (!DVT && SVT && SVT->getElementType() == ToTy) {
144 Output = loadFirstValueFromAggregate(
B, SVT->getElementType(),
145 OriginalOperand, LI);
151 Output = loadVectorFromVector(
B, SVT, DVT, OriginalOperand);
155 else if (SST && SST->getTypeAtIndex(0u) == ToTy)
156 Output = loadFirstValueFromAggregate(
B, ToTy, OriginalOperand, LI);
160 GR->replaceAllUsesWith(LI, Output,
true);
161 DeadInstructions.push_back(LI);
172 B.CreateIntrinsic(Intrinsic::spv_insertelt, {
Types}, {
Args});
173 buildAssignType(
B,
Vector->getType(), NewI);
185 B.CreateIntrinsic(Intrinsic::spv_extractelt, {
Types}, {
Args});
186 buildAssignType(
B, ElementType, NewI);
195 FixedVectorType *DstType =
204 [[maybe_unused]]
auto dstBitWidth =
206 [[maybe_unused]]
auto srcBitWidth =
208 assert(dstBitWidth == srcBitWidth &&
209 "Unsupported bitcast between vectors of different sizes.");
212 B.CreateIntrinsic(Intrinsic::spv_bitcast, {DstType, SrcType}, {Src});
213 buildAssignType(
B, DstType, Src);
216 StoreInst *
SI =
B.CreateStore(Src, Dst);
217 SI->setAlignment(Alignment);
222 LoadInst *LI =
B.CreateLoad(DstType, Dst);
224 Value *OldValues = LI;
225 buildAssignType(
B, OldValues->
getType(), OldValues);
226 Value *NewValues = Src;
231 OldValues = makeInsertElement(
B, OldValues, Element,
I);
234 StoreInst *
SI =
B.CreateStore(OldValues, Dst);
235 SI->setAlignment(Alignment);
240 SmallVectorImpl<Value *> &Indices) {
243 if (Search == Aggregate)
247 buildGEPIndexChain(
B, Search,
ST->getTypeAtIndex(0u), Indices);
249 buildGEPIndexChain(
B, Search, AT->getElementType(), Indices);
251 buildGEPIndexChain(
B, Search, VT->getElementType(), Indices);
258 Type *DstPointeeType, Align Alignment) {
261 buildGEPIndexChain(
B, Src->getType(), DstPointeeType, Args);
262 auto *
GEP =
B.CreateIntrinsic(Intrinsic::spv_gep, {
Types}, {
Args});
263 GR->buildAssignPtr(
B, Src->getType(),
GEP);
264 StoreInst *
SI =
B.CreateStore(Src,
GEP);
265 SI->setAlignment(Alignment);
269 bool isTypeFirstElementAggregate(
Type *Search,
Type *Aggregate) {
270 if (Search == Aggregate)
273 return isTypeFirstElementAggregate(Search,
ST->getTypeAtIndex(0u));
275 return isTypeFirstElementAggregate(Search, VT->getElementType());
277 return isTypeFirstElementAggregate(Search, AT->getElementType());
284 Value *Dst, Align Alignment) {
285 Type *ToTy = GR->findDeducedElementType(Dst);
286 Type *FromTy = Src->getType();
292 B.SetInsertPoint(BadStore);
293 if (D_ST && isTypeFirstElementAggregate(FromTy, D_ST))
294 storeToFirstValueAggregate(
B, Src, Dst, D_ST, Alignment);
295 else if (D_VT && S_VT)
296 storeVectorFromVector(
B, Src, Dst, Alignment);
297 else if (D_VT && !S_VT && FromTy == D_VT->getElementType())
298 storeToFirstValueAggregate(
B, Src, Dst, D_VT, Alignment);
302 DeadInstructions.push_back(BadStore);
305 void legalizePointerCast(IntrinsicInst *
II) {
307 Value *OriginalOperand =
II->getOperand(0);
310 std::vector<Value *>
Users;
311 for (Use &U :
II->uses())
312 Users.push_back(
U.getUser());
316 transformLoad(
B, LI, CastedOperand, OriginalOperand);
321 transformStore(
B, SI,
SI->getValueOperand(), OriginalOperand,
327 if (Intrin->getIntrinsicID() == Intrinsic::spv_assign_ptr_type) {
328 DeadInstructions.push_back(Intrin);
332 if (Intrin->getIntrinsicID() == Intrinsic::spv_gep) {
333 GR->replaceAllUsesWith(CastedOperand, OriginalOperand,
338 if (Intrin->getIntrinsicID() == Intrinsic::spv_store) {
341 Alignment =
Align(
C->getZExtValue());
342 transformStore(
B, Intrin, Intrin->getArgOperand(0), OriginalOperand,
351 DeadInstructions.push_back(
II);
355 SPIRVLegalizePointerCast(SPIRVTargetMachine *TM) : FunctionPass(ID), TM(TM) {}
358 const SPIRVSubtarget &
ST = TM->getSubtarget<SPIRVSubtarget>(
F);
359 GR =
ST.getSPIRVGlobalRegistry();
360 DeadInstructions.clear();
362 std::vector<IntrinsicInst *> WorkList;
366 if (
II &&
II->getIntrinsicID() == Intrinsic::spv_ptrcast)
367 WorkList.push_back(
II);
371 for (IntrinsicInst *
II : WorkList)
372 legalizePointerCast(
II);
374 for (Instruction *
I : DeadInstructions)
375 I->eraseFromParent();
377 return DeadInstructions.size() != 0;
381 SPIRVTargetMachine *TM =
nullptr;
382 SPIRVGlobalRegistry *GR =
nullptr;
383 std::vector<Instruction *> DeadInstructions;
390char SPIRVLegalizePointerCast::ID = 0;
392 "SPIRV legalize bitcast pass",
false,
false)
395 return new SPIRVLegalizePointerCast(TM);
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)
iv Induction Variable Users
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
unsigned getNumElements() const
FunctionPass class - This class is used to implement most global optimizations.
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.
Type * getType() const
All values are typed, get the type of this value.
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.
ElementType
The element type of an SRV or UAV resource.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
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.
FunctionPass * createSPIRVLegalizePointerCastPass(SPIRVTargetMachine *TM)