53#include "llvm/IR/IntrinsicsSPIRV.h"
67 {Arg->
getType()}, OfType, Arg, {},
B);
68 GR->addAssignPtrTypeInstr(Arg, AssignCI);
78 LoadInst *NewLoad =
B.CreateLoad(SourceType, Source);
79 buildAssignType(
B, SourceType, NewLoad);
80 Value *AssignValue = NewLoad;
82 AssignValue =
B.CreateIntrinsic(Intrinsic::spv_bitcast,
83 {TargetType, SourceType}, {NewLoad});
84 buildAssignType(
B, TargetType, AssignValue);
90 Value *Output =
B.CreateShuffleVector(AssignValue, AssignValue, Mask);
91 buildAssignType(
B, TargetType, Output);
103 B.getInt32(0),
B.getInt32(0)};
104 auto *
GEP =
B.CreateIntrinsic(Intrinsic::spv_gep, {
Types}, {
Args});
105 GR->buildAssignPtr(
B, ElementType,
GEP);
109 buildAssignType(
B, ElementType, LI);
116 Value *OriginalOperand) {
117 Type *FromTy = GR->findDeducedElementType(OriginalOperand);
118 Type *ToTy = GR->findDeducedElementType(CastedOperand);
119 Value *Output =
nullptr;
121 auto *
SAT = dyn_cast<ArrayType>(FromTy);
122 auto *SVT = dyn_cast<FixedVectorType>(FromTy);
123 auto *SST = dyn_cast<StructType>(FromTy);
124 auto *DVT = dyn_cast<FixedVectorType>(ToTy);
126 B.SetInsertPoint(LI);
131 if (
SAT &&
SAT->getElementType() == ToTy)
132 Output = loadFirstValueFromAggregate(
B,
SAT->getElementType(),
133 OriginalOperand, LI);
137 else if (!DVT && SVT && SVT->getElementType() == ToTy) {
138 Output = loadFirstValueFromAggregate(
B, SVT->getElementType(),
139 OriginalOperand, LI);
145 Output = loadVectorFromVector(
B, SVT, DVT, OriginalOperand);
149 else if (SST && SST->getTypeAtIndex(0u) == ToTy)
150 Output = loadFirstValueFromAggregate(
B, ToTy, OriginalOperand, LI);
154 GR->replaceAllUsesWith(LI, Output,
true);
155 DeadInstructions.push_back(LI);
166 B.CreateIntrinsic(Intrinsic::spv_insertelt, {
Types}, {
Args});
167 buildAssignType(
B,
Vector->getType(), NewI);
179 B.CreateIntrinsic(Intrinsic::spv_extractelt, {
Types}, {
Args});
180 buildAssignType(
B, ElementType, NewI);
190 cast<FixedVectorType>(GR->findDeducedElementType(Dst));
193 LoadInst *LI =
B.CreateLoad(DstType, Dst);
195 Value *OldValues = LI;
196 buildAssignType(
B, OldValues->
getType(), OldValues);
197 Value *NewValues = Src;
202 OldValues = makeInsertElement(
B, OldValues, Element,
I);
206 SI->setAlignment(Alignment);
214 if (Search == Aggregate)
217 if (
auto *ST = dyn_cast<StructType>(Aggregate))
218 buildGEPIndexChain(
B, Search,
ST->getTypeAtIndex(0u), Indices);
219 else if (
auto *AT = dyn_cast<ArrayType>(Aggregate))
220 buildGEPIndexChain(
B, Search, AT->getElementType(), Indices);
221 else if (
auto *VT = dyn_cast<FixedVectorType>(Aggregate))
222 buildGEPIndexChain(
B, Search, VT->getElementType(), Indices);
232 buildGEPIndexChain(
B, Src->getType(), DstPointeeType, Args);
233 auto *
GEP =
B.CreateIntrinsic(Intrinsic::spv_gep, {
Types}, {
Args});
234 GR->buildAssignPtr(
B, Src->getType(),
GEP);
236 SI->setAlignment(Alignment);
240 bool isTypeFirstElementAggregate(
Type *Search,
Type *Aggregate) {
241 if (Search == Aggregate)
243 if (
auto *ST = dyn_cast<StructType>(Aggregate))
244 return isTypeFirstElementAggregate(Search,
ST->getTypeAtIndex(0u));
245 if (
auto *VT = dyn_cast<FixedVectorType>(Aggregate))
246 return isTypeFirstElementAggregate(Search, VT->getElementType());
247 if (
auto *AT = dyn_cast<ArrayType>(Aggregate))
248 return isTypeFirstElementAggregate(Search, AT->getElementType());
256 Type *ToTy = GR->findDeducedElementType(Dst);
257 Type *FromTy = Src->getType();
259 auto *S_VT = dyn_cast<FixedVectorType>(FromTy);
260 auto *D_ST = dyn_cast<StructType>(ToTy);
261 auto *D_VT = dyn_cast<FixedVectorType>(ToTy);
263 B.SetInsertPoint(BadStore);
264 if (D_ST && isTypeFirstElementAggregate(FromTy, D_ST))
265 storeToFirstValueAggregate(
B, Src, Dst, D_ST, Alignment);
266 else if (D_VT && S_VT)
267 storeVectorFromVector(
B, Src, Dst, Alignment);
268 else if (D_VT && !S_VT && FromTy == D_VT->getElementType())
269 storeToFirstValueAggregate(
B, Src, Dst, D_VT, Alignment);
273 DeadInstructions.push_back(BadStore);
278 Value *OriginalOperand =
II->getOperand(0);
281 std::vector<Value *>
Users;
282 for (
Use &U :
II->uses())
283 Users.push_back(
U.getUser());
287 transformLoad(
B, LI, CastedOperand, OriginalOperand);
292 transformStore(
B, SI,
SI->getValueOperand(), OriginalOperand,
298 if (Intrin->getIntrinsicID() == Intrinsic::spv_assign_ptr_type) {
299 DeadInstructions.push_back(Intrin);
303 if (Intrin->getIntrinsicID() == Intrinsic::spv_gep) {
304 GR->replaceAllUsesWith(CastedOperand, OriginalOperand,
309 if (Intrin->getIntrinsicID() == Intrinsic::spv_store) {
311 if (
ConstantInt *
C = dyn_cast<ConstantInt>(Intrin->getOperand(3)))
312 Alignment =
Align(
C->getZExtValue());
313 transformStore(
B, Intrin, Intrin->getArgOperand(0), OriginalOperand,
322 DeadInstructions.push_back(
II);
330 GR =
ST.getSPIRVGlobalRegistry();
331 DeadInstructions.clear();
333 std::vector<IntrinsicInst *> WorkList;
336 auto *
II = dyn_cast<IntrinsicInst>(&
I);
337 if (
II &&
II->getIntrinsicID() == Intrinsic::spv_ptrcast)
338 WorkList.push_back(
II);
343 legalizePointerCast(
II);
346 I->eraseFromParent();
348 return DeadInstructions.size() != 0;
354 std::vector<Instruction *> DeadInstructions;
361char SPIRVLegalizePointerCast::ID = 0;
363 "SPIRV legalize bitcast pass",
false,
false)
366 return new SPIRVLegalizePointerCast(TM);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
iv Induction Variable Users
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This class represents a function call, abstracting a target machine's calling convention.
This is the shared class of boolean and integer constants.
Class to represent fixed width SIMD vectors.
unsigned getNumElements() const
FunctionPass class - This class is used to implement most global optimizations.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
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.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
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 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
ElementType
The element type of an SRV or UAV resource.
This is an optimization pass for GlobalISel generic memory operations.
CallInst * buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef< Type * > Types, Value *Arg, Value *Arg2, ArrayRef< Constant * > Imms, IRBuilder<> &B)
FunctionPass * createSPIRVLegalizePointerCastPass(SPIRVTargetMachine *TM)
This struct is a compact representation of a valid (non-zero power of two) alignment.