xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===-- SPIRVEmitIntrinsics.cpp - emit SPIRV intrinsics ---------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // The pass emits SPIRV intrinsics keeping essential high-level information for
1081ad6265SDimitry Andric // the translation of LLVM IR to SPIR-V.
1181ad6265SDimitry Andric //
1281ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1381ad6265SDimitry Andric 
1481ad6265SDimitry Andric #include "SPIRV.h"
15*0fca6ea1SDimitry Andric #include "SPIRVBuiltins.h"
16*0fca6ea1SDimitry Andric #include "SPIRVMetadata.h"
17*0fca6ea1SDimitry Andric #include "SPIRVSubtarget.h"
1881ad6265SDimitry Andric #include "SPIRVTargetMachine.h"
1981ad6265SDimitry Andric #include "SPIRVUtils.h"
2081ad6265SDimitry Andric #include "llvm/IR/IRBuilder.h"
2181ad6265SDimitry Andric #include "llvm/IR/InstIterator.h"
2281ad6265SDimitry Andric #include "llvm/IR/InstVisitor.h"
2381ad6265SDimitry Andric #include "llvm/IR/IntrinsicsSPIRV.h"
24*0fca6ea1SDimitry Andric #include "llvm/IR/TypedPointerType.h"
2581ad6265SDimitry Andric 
2681ad6265SDimitry Andric #include <queue>
2781ad6265SDimitry Andric 
2881ad6265SDimitry Andric // This pass performs the following transformation on LLVM IR level required
2981ad6265SDimitry Andric // for the following translation to SPIR-V:
3081ad6265SDimitry Andric // - replaces direct usages of aggregate constants with target-specific
3181ad6265SDimitry Andric //   intrinsics;
3281ad6265SDimitry Andric // - replaces aggregates-related instructions (extract/insert, ld/st, etc)
3381ad6265SDimitry Andric //   with a target-specific intrinsics;
3481ad6265SDimitry Andric // - emits intrinsics for the global variable initializers since IRTranslator
3581ad6265SDimitry Andric //   doesn't handle them and it's not very convenient to translate them
3681ad6265SDimitry Andric //   ourselves;
3781ad6265SDimitry Andric // - emits intrinsics to keep track of the string names assigned to the values;
3881ad6265SDimitry Andric // - emits intrinsics to keep track of constants (this is necessary to have an
3981ad6265SDimitry Andric //   LLVM IR constant after the IRTranslation is completed) for their further
4081ad6265SDimitry Andric //   deduplication;
4181ad6265SDimitry Andric // - emits intrinsics to keep track of original LLVM types of the values
4281ad6265SDimitry Andric //   to be able to emit proper SPIR-V types eventually.
4381ad6265SDimitry Andric //
4481ad6265SDimitry Andric // TODO: consider removing spv.track.constant in favor of spv.assign.type.
4581ad6265SDimitry Andric 
4681ad6265SDimitry Andric using namespace llvm;
4781ad6265SDimitry Andric 
4881ad6265SDimitry Andric namespace llvm {
49*0fca6ea1SDimitry Andric namespace SPIRV {
50*0fca6ea1SDimitry Andric #define GET_BuiltinGroup_DECL
51*0fca6ea1SDimitry Andric #include "SPIRVGenTables.inc"
52*0fca6ea1SDimitry Andric } // namespace SPIRV
5381ad6265SDimitry Andric void initializeSPIRVEmitIntrinsicsPass(PassRegistry &);
5481ad6265SDimitry Andric } // namespace llvm
5581ad6265SDimitry Andric 
5681ad6265SDimitry Andric namespace {
57*0fca6ea1SDimitry Andric 
58*0fca6ea1SDimitry Andric inline MetadataAsValue *buildMD(Value *Arg) {
59*0fca6ea1SDimitry Andric   LLVMContext &Ctx = Arg->getContext();
60*0fca6ea1SDimitry Andric   return MetadataAsValue::get(
61*0fca6ea1SDimitry Andric       Ctx, MDNode::get(Ctx, ValueAsMetadata::getConstant(Arg)));
62*0fca6ea1SDimitry Andric }
63*0fca6ea1SDimitry Andric 
6481ad6265SDimitry Andric class SPIRVEmitIntrinsics
65*0fca6ea1SDimitry Andric     : public ModulePass,
6681ad6265SDimitry Andric       public InstVisitor<SPIRVEmitIntrinsics, Instruction *> {
6781ad6265SDimitry Andric   SPIRVTargetMachine *TM = nullptr;
68*0fca6ea1SDimitry Andric   SPIRVGlobalRegistry *GR = nullptr;
6981ad6265SDimitry Andric   Function *F = nullptr;
7081ad6265SDimitry Andric   bool TrackConstants = true;
7181ad6265SDimitry Andric   DenseMap<Instruction *, Constant *> AggrConsts;
72*0fca6ea1SDimitry Andric   DenseMap<Instruction *, Type *> AggrConstTypes;
7381ad6265SDimitry Andric   DenseSet<Instruction *> AggrStores;
74*0fca6ea1SDimitry Andric   SPIRV::InstructionSet::InstructionSet InstrSet;
75*0fca6ea1SDimitry Andric 
76*0fca6ea1SDimitry Andric   // a register of Instructions that don't have a complete type definition
77*0fca6ea1SDimitry Andric   SmallPtrSet<Value *, 8> UncompleteTypeInfo;
78*0fca6ea1SDimitry Andric   SmallVector<Instruction *> PostprocessWorklist;
79*0fca6ea1SDimitry Andric 
80*0fca6ea1SDimitry Andric   // well known result types of builtins
81*0fca6ea1SDimitry Andric   enum WellKnownTypes { Event };
82*0fca6ea1SDimitry Andric 
83*0fca6ea1SDimitry Andric   // deduce element type of untyped pointers
84*0fca6ea1SDimitry Andric   Type *deduceElementType(Value *I, bool UnknownElemTypeI8);
85*0fca6ea1SDimitry Andric   Type *deduceElementTypeHelper(Value *I, bool UnknownElemTypeI8);
86*0fca6ea1SDimitry Andric   Type *deduceElementTypeHelper(Value *I, std::unordered_set<Value *> &Visited,
87*0fca6ea1SDimitry Andric                                 bool UnknownElemTypeI8);
88*0fca6ea1SDimitry Andric   Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
89*0fca6ea1SDimitry Andric                                      bool UnknownElemTypeI8);
90*0fca6ea1SDimitry Andric   Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
91*0fca6ea1SDimitry Andric                                      std::unordered_set<Value *> &Visited,
92*0fca6ea1SDimitry Andric                                      bool UnknownElemTypeI8);
93*0fca6ea1SDimitry Andric   Type *deduceElementTypeByUsersDeep(Value *Op,
94*0fca6ea1SDimitry Andric                                      std::unordered_set<Value *> &Visited,
95*0fca6ea1SDimitry Andric                                      bool UnknownElemTypeI8);
96*0fca6ea1SDimitry Andric   void maybeAssignPtrType(Type *&Ty, Value *I, Type *RefTy,
97*0fca6ea1SDimitry Andric                           bool UnknownElemTypeI8);
98*0fca6ea1SDimitry Andric 
99*0fca6ea1SDimitry Andric   // deduce nested types of composites
100*0fca6ea1SDimitry Andric   Type *deduceNestedTypeHelper(User *U, bool UnknownElemTypeI8);
101*0fca6ea1SDimitry Andric   Type *deduceNestedTypeHelper(User *U, Type *Ty,
102*0fca6ea1SDimitry Andric                                std::unordered_set<Value *> &Visited,
103*0fca6ea1SDimitry Andric                                bool UnknownElemTypeI8);
104*0fca6ea1SDimitry Andric 
105*0fca6ea1SDimitry Andric   // deduce Types of operands of the Instruction if possible
106*0fca6ea1SDimitry Andric   void deduceOperandElementType(Instruction *I, Instruction *AskOp = 0,
107*0fca6ea1SDimitry Andric                                 Type *AskTy = 0, CallInst *AssignCI = 0);
108*0fca6ea1SDimitry Andric 
109*0fca6ea1SDimitry Andric   void preprocessCompositeConstants(IRBuilder<> &B);
110*0fca6ea1SDimitry Andric   void preprocessUndefs(IRBuilder<> &B);
111*0fca6ea1SDimitry Andric 
11281ad6265SDimitry Andric   CallInst *buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef<Type *> Types,
113*0fca6ea1SDimitry Andric                             Value *Arg, Value *Arg2, ArrayRef<Constant *> Imms,
114*0fca6ea1SDimitry Andric                             IRBuilder<> &B) {
1155f757f3fSDimitry Andric     SmallVector<Value *, 4> Args;
1165f757f3fSDimitry Andric     Args.push_back(Arg2);
117*0fca6ea1SDimitry Andric     Args.push_back(buildMD(Arg));
1185f757f3fSDimitry Andric     for (auto *Imm : Imms)
1195f757f3fSDimitry Andric       Args.push_back(Imm);
120*0fca6ea1SDimitry Andric     return B.CreateIntrinsic(IntrID, {Types}, Args);
12181ad6265SDimitry Andric   }
122*0fca6ea1SDimitry Andric 
123*0fca6ea1SDimitry Andric   void buildAssignType(IRBuilder<> &B, Type *ElemTy, Value *Arg);
124*0fca6ea1SDimitry Andric   void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg);
125*0fca6ea1SDimitry Andric   void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType);
126*0fca6ea1SDimitry Andric 
127*0fca6ea1SDimitry Andric   void replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B);
128*0fca6ea1SDimitry Andric   void processInstrAfterVisit(Instruction *I, IRBuilder<> &B);
129*0fca6ea1SDimitry Andric   bool insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B,
130*0fca6ea1SDimitry Andric                                 bool UnknownElemTypeI8);
131*0fca6ea1SDimitry Andric   void insertAssignTypeIntrs(Instruction *I, IRBuilder<> &B);
132*0fca6ea1SDimitry Andric   void insertAssignPtrTypeTargetExt(TargetExtType *AssignedType, Value *V,
133*0fca6ea1SDimitry Andric                                     IRBuilder<> &B);
134*0fca6ea1SDimitry Andric   void replacePointerOperandWithPtrCast(Instruction *I, Value *Pointer,
135*0fca6ea1SDimitry Andric                                         Type *ExpectedElementType,
136*0fca6ea1SDimitry Andric                                         unsigned OperandToReplace,
137*0fca6ea1SDimitry Andric                                         IRBuilder<> &B);
138*0fca6ea1SDimitry Andric   void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B);
139*0fca6ea1SDimitry Andric   void insertSpirvDecorations(Instruction *I, IRBuilder<> &B);
140*0fca6ea1SDimitry Andric   void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B);
141*0fca6ea1SDimitry Andric   void processParamTypes(Function *F, IRBuilder<> &B);
142*0fca6ea1SDimitry Andric   void processParamTypesByFunHeader(Function *F, IRBuilder<> &B);
143*0fca6ea1SDimitry Andric   Type *deduceFunParamElementType(Function *F, unsigned OpIdx);
144*0fca6ea1SDimitry Andric   Type *deduceFunParamElementType(Function *F, unsigned OpIdx,
145*0fca6ea1SDimitry Andric                                   std::unordered_set<Function *> &FVisited);
14681ad6265SDimitry Andric 
14781ad6265SDimitry Andric public:
14881ad6265SDimitry Andric   static char ID;
149*0fca6ea1SDimitry Andric   SPIRVEmitIntrinsics() : ModulePass(ID) {
15081ad6265SDimitry Andric     initializeSPIRVEmitIntrinsicsPass(*PassRegistry::getPassRegistry());
15181ad6265SDimitry Andric   }
152*0fca6ea1SDimitry Andric   SPIRVEmitIntrinsics(SPIRVTargetMachine *_TM) : ModulePass(ID), TM(_TM) {
15381ad6265SDimitry Andric     initializeSPIRVEmitIntrinsicsPass(*PassRegistry::getPassRegistry());
15481ad6265SDimitry Andric   }
15581ad6265SDimitry Andric   Instruction *visitInstruction(Instruction &I) { return &I; }
15681ad6265SDimitry Andric   Instruction *visitSwitchInst(SwitchInst &I);
15781ad6265SDimitry Andric   Instruction *visitGetElementPtrInst(GetElementPtrInst &I);
15881ad6265SDimitry Andric   Instruction *visitBitCastInst(BitCastInst &I);
15981ad6265SDimitry Andric   Instruction *visitInsertElementInst(InsertElementInst &I);
16081ad6265SDimitry Andric   Instruction *visitExtractElementInst(ExtractElementInst &I);
16181ad6265SDimitry Andric   Instruction *visitInsertValueInst(InsertValueInst &I);
16281ad6265SDimitry Andric   Instruction *visitExtractValueInst(ExtractValueInst &I);
16381ad6265SDimitry Andric   Instruction *visitLoadInst(LoadInst &I);
16481ad6265SDimitry Andric   Instruction *visitStoreInst(StoreInst &I);
16581ad6265SDimitry Andric   Instruction *visitAllocaInst(AllocaInst &I);
166fcaf7f86SDimitry Andric   Instruction *visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);
167bdd1243dSDimitry Andric   Instruction *visitUnreachableInst(UnreachableInst &I);
168*0fca6ea1SDimitry Andric   Instruction *visitCallInst(CallInst &I);
169*0fca6ea1SDimitry Andric 
170*0fca6ea1SDimitry Andric   StringRef getPassName() const override { return "SPIRV emit intrinsics"; }
171*0fca6ea1SDimitry Andric 
172*0fca6ea1SDimitry Andric   bool runOnModule(Module &M) override;
173*0fca6ea1SDimitry Andric   bool runOnFunction(Function &F);
174*0fca6ea1SDimitry Andric   bool postprocessTypes();
175*0fca6ea1SDimitry Andric 
176*0fca6ea1SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
177*0fca6ea1SDimitry Andric     ModulePass::getAnalysisUsage(AU);
178*0fca6ea1SDimitry Andric   }
17981ad6265SDimitry Andric };
180*0fca6ea1SDimitry Andric 
181*0fca6ea1SDimitry Andric bool isConvergenceIntrinsic(const Instruction *I) {
182*0fca6ea1SDimitry Andric   const auto *II = dyn_cast<IntrinsicInst>(I);
183*0fca6ea1SDimitry Andric   if (!II)
184*0fca6ea1SDimitry Andric     return false;
185*0fca6ea1SDimitry Andric 
186*0fca6ea1SDimitry Andric   return II->getIntrinsicID() == Intrinsic::experimental_convergence_entry ||
187*0fca6ea1SDimitry Andric          II->getIntrinsicID() == Intrinsic::experimental_convergence_loop ||
188*0fca6ea1SDimitry Andric          II->getIntrinsicID() == Intrinsic::experimental_convergence_anchor;
189*0fca6ea1SDimitry Andric }
19081ad6265SDimitry Andric } // namespace
19181ad6265SDimitry Andric 
19281ad6265SDimitry Andric char SPIRVEmitIntrinsics::ID = 0;
19381ad6265SDimitry Andric 
19481ad6265SDimitry Andric INITIALIZE_PASS(SPIRVEmitIntrinsics, "emit-intrinsics", "SPIRV emit intrinsics",
19581ad6265SDimitry Andric                 false, false)
19681ad6265SDimitry Andric 
19781ad6265SDimitry Andric static inline bool isAssignTypeInstr(const Instruction *I) {
19881ad6265SDimitry Andric   return isa<IntrinsicInst>(I) &&
19981ad6265SDimitry Andric          cast<IntrinsicInst>(I)->getIntrinsicID() == Intrinsic::spv_assign_type;
20081ad6265SDimitry Andric }
20181ad6265SDimitry Andric 
20281ad6265SDimitry Andric static bool isMemInstrToReplace(Instruction *I) {
20381ad6265SDimitry Andric   return isa<StoreInst>(I) || isa<LoadInst>(I) || isa<InsertValueInst>(I) ||
204fcaf7f86SDimitry Andric          isa<ExtractValueInst>(I) || isa<AtomicCmpXchgInst>(I);
20581ad6265SDimitry Andric }
20681ad6265SDimitry Andric 
207*0fca6ea1SDimitry Andric static bool isAggrConstForceInt32(const Value *V) {
208*0fca6ea1SDimitry Andric   return isa<ConstantArray>(V) || isa<ConstantStruct>(V) ||
209*0fca6ea1SDimitry Andric          isa<ConstantDataArray>(V) ||
21081ad6265SDimitry Andric          (isa<ConstantAggregateZero>(V) && !V->getType()->isVectorTy());
21181ad6265SDimitry Andric }
21281ad6265SDimitry Andric 
21381ad6265SDimitry Andric static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I) {
21481ad6265SDimitry Andric   if (isa<PHINode>(I))
215*0fca6ea1SDimitry Andric     B.SetInsertPoint(I->getParent()->getFirstNonPHIOrDbgOrAlloca());
21681ad6265SDimitry Andric   else
21781ad6265SDimitry Andric     B.SetInsertPoint(I);
21881ad6265SDimitry Andric }
21981ad6265SDimitry Andric 
220*0fca6ea1SDimitry Andric static void setInsertPointAfterDef(IRBuilder<> &B, Instruction *I) {
221*0fca6ea1SDimitry Andric   B.SetCurrentDebugLocation(I->getDebugLoc());
222*0fca6ea1SDimitry Andric   if (I->getType()->isVoidTy())
223*0fca6ea1SDimitry Andric     B.SetInsertPoint(I->getNextNode());
224*0fca6ea1SDimitry Andric   else
225*0fca6ea1SDimitry Andric     B.SetInsertPoint(*I->getInsertionPointAfterDef());
2265f757f3fSDimitry Andric }
2275f757f3fSDimitry Andric 
22881ad6265SDimitry Andric static bool requireAssignType(Instruction *I) {
22981ad6265SDimitry Andric   IntrinsicInst *Intr = dyn_cast<IntrinsicInst>(I);
23081ad6265SDimitry Andric   if (Intr) {
23181ad6265SDimitry Andric     switch (Intr->getIntrinsicID()) {
23281ad6265SDimitry Andric     case Intrinsic::invariant_start:
23381ad6265SDimitry Andric     case Intrinsic::invariant_end:
23481ad6265SDimitry Andric       return false;
23581ad6265SDimitry Andric     }
23681ad6265SDimitry Andric   }
23781ad6265SDimitry Andric   return true;
23881ad6265SDimitry Andric }
23981ad6265SDimitry Andric 
240*0fca6ea1SDimitry Andric static inline void reportFatalOnTokenType(const Instruction *I) {
241*0fca6ea1SDimitry Andric   if (I->getType()->isTokenTy())
242*0fca6ea1SDimitry Andric     report_fatal_error("A token is encountered but SPIR-V without extensions "
243*0fca6ea1SDimitry Andric                        "does not support token type",
244*0fca6ea1SDimitry Andric                        false);
245*0fca6ea1SDimitry Andric }
246*0fca6ea1SDimitry Andric 
247*0fca6ea1SDimitry Andric static bool IsKernelArgInt8(Function *F, StoreInst *SI) {
248*0fca6ea1SDimitry Andric   return SI && F->getCallingConv() == CallingConv::SPIR_KERNEL &&
249*0fca6ea1SDimitry Andric          isPointerTy(SI->getValueOperand()->getType()) &&
250*0fca6ea1SDimitry Andric          isa<Argument>(SI->getValueOperand());
251*0fca6ea1SDimitry Andric }
252*0fca6ea1SDimitry Andric 
253*0fca6ea1SDimitry Andric // Maybe restore original function return type.
254*0fca6ea1SDimitry Andric static inline Type *restoreMutatedType(SPIRVGlobalRegistry *GR, Instruction *I,
255*0fca6ea1SDimitry Andric                                        Type *Ty) {
256*0fca6ea1SDimitry Andric   CallInst *CI = dyn_cast<CallInst>(I);
257*0fca6ea1SDimitry Andric   if (!CI || CI->isIndirectCall() || CI->isInlineAsm() ||
258*0fca6ea1SDimitry Andric       !CI->getCalledFunction() || CI->getCalledFunction()->isIntrinsic())
259*0fca6ea1SDimitry Andric     return Ty;
260*0fca6ea1SDimitry Andric   if (Type *OriginalTy = GR->findMutated(CI->getCalledFunction()))
261*0fca6ea1SDimitry Andric     return OriginalTy;
262*0fca6ea1SDimitry Andric   return Ty;
263*0fca6ea1SDimitry Andric }
264*0fca6ea1SDimitry Andric 
265*0fca6ea1SDimitry Andric // Reconstruct type with nested element types according to deduced type info.
266*0fca6ea1SDimitry Andric // Return nullptr if no detailed type info is available.
267*0fca6ea1SDimitry Andric static inline Type *reconstructType(SPIRVGlobalRegistry *GR, Value *Op) {
268*0fca6ea1SDimitry Andric   Type *Ty = Op->getType();
269*0fca6ea1SDimitry Andric   if (!isUntypedPointerTy(Ty))
270*0fca6ea1SDimitry Andric     return Ty;
271*0fca6ea1SDimitry Andric   // try to find the pointee type
272*0fca6ea1SDimitry Andric   if (Type *NestedTy = GR->findDeducedElementType(Op))
273*0fca6ea1SDimitry Andric     return getTypedPointerWrapper(NestedTy, getPointerAddressSpace(Ty));
274*0fca6ea1SDimitry Andric   // not a pointer according to the type info (e.g., Event object)
275*0fca6ea1SDimitry Andric   CallInst *CI = GR->findAssignPtrTypeInstr(Op);
276*0fca6ea1SDimitry Andric   if (!CI)
277*0fca6ea1SDimitry Andric     return nullptr;
278*0fca6ea1SDimitry Andric   MetadataAsValue *MD = cast<MetadataAsValue>(CI->getArgOperand(1));
279*0fca6ea1SDimitry Andric   return cast<ConstantAsMetadata>(MD->getMetadata())->getType();
280*0fca6ea1SDimitry Andric }
281*0fca6ea1SDimitry Andric 
282*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::buildAssignType(IRBuilder<> &B, Type *Ty,
283*0fca6ea1SDimitry Andric                                           Value *Arg) {
284*0fca6ea1SDimitry Andric   Value *OfType = PoisonValue::get(Ty);
285*0fca6ea1SDimitry Andric   CallInst *AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type,
286*0fca6ea1SDimitry Andric                                        {Arg->getType()}, OfType, Arg, {}, B);
287*0fca6ea1SDimitry Andric   GR->addAssignPtrTypeInstr(Arg, AssignCI);
288*0fca6ea1SDimitry Andric }
289*0fca6ea1SDimitry Andric 
290*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::buildAssignPtr(IRBuilder<> &B, Type *ElemTy,
291*0fca6ea1SDimitry Andric                                          Value *Arg) {
292*0fca6ea1SDimitry Andric   Value *OfType = PoisonValue::get(ElemTy);
293*0fca6ea1SDimitry Andric   CallInst *AssignPtrTyCI = GR->findAssignPtrTypeInstr(Arg);
294*0fca6ea1SDimitry Andric   if (AssignPtrTyCI == nullptr ||
295*0fca6ea1SDimitry Andric       AssignPtrTyCI->getParent()->getParent() != F) {
296*0fca6ea1SDimitry Andric     AssignPtrTyCI = buildIntrWithMD(
297*0fca6ea1SDimitry Andric         Intrinsic::spv_assign_ptr_type, {Arg->getType()}, OfType, Arg,
298*0fca6ea1SDimitry Andric         {B.getInt32(getPointerAddressSpace(Arg->getType()))}, B);
299*0fca6ea1SDimitry Andric     GR->addDeducedElementType(AssignPtrTyCI, ElemTy);
300*0fca6ea1SDimitry Andric     GR->addDeducedElementType(Arg, ElemTy);
301*0fca6ea1SDimitry Andric     GR->addAssignPtrTypeInstr(Arg, AssignPtrTyCI);
302*0fca6ea1SDimitry Andric   } else {
303*0fca6ea1SDimitry Andric     updateAssignType(AssignPtrTyCI, Arg, OfType);
304*0fca6ea1SDimitry Andric   }
305*0fca6ea1SDimitry Andric }
306*0fca6ea1SDimitry Andric 
307*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::updateAssignType(CallInst *AssignCI, Value *Arg,
308*0fca6ea1SDimitry Andric                                            Value *OfType) {
309*0fca6ea1SDimitry Andric   AssignCI->setArgOperand(1, buildMD(OfType));
310*0fca6ea1SDimitry Andric   if (cast<IntrinsicInst>(AssignCI)->getIntrinsicID() !=
311*0fca6ea1SDimitry Andric       Intrinsic::spv_assign_ptr_type)
312*0fca6ea1SDimitry Andric     return;
313*0fca6ea1SDimitry Andric 
314*0fca6ea1SDimitry Andric   // update association with the pointee type
315*0fca6ea1SDimitry Andric   Type *ElemTy = OfType->getType();
316*0fca6ea1SDimitry Andric   GR->addDeducedElementType(AssignCI, ElemTy);
317*0fca6ea1SDimitry Andric   GR->addDeducedElementType(Arg, ElemTy);
318*0fca6ea1SDimitry Andric }
319*0fca6ea1SDimitry Andric 
320*0fca6ea1SDimitry Andric // Set element pointer type to the given value of ValueTy and tries to
321*0fca6ea1SDimitry Andric // specify this type further (recursively) by Operand value, if needed.
322*0fca6ea1SDimitry Andric Type *
323*0fca6ea1SDimitry Andric SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
324*0fca6ea1SDimitry Andric                                                   bool UnknownElemTypeI8) {
325*0fca6ea1SDimitry Andric   std::unordered_set<Value *> Visited;
326*0fca6ea1SDimitry Andric   return deduceElementTypeByValueDeep(ValueTy, Operand, Visited,
327*0fca6ea1SDimitry Andric                                       UnknownElemTypeI8);
328*0fca6ea1SDimitry Andric }
329*0fca6ea1SDimitry Andric 
330*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(
331*0fca6ea1SDimitry Andric     Type *ValueTy, Value *Operand, std::unordered_set<Value *> &Visited,
332*0fca6ea1SDimitry Andric     bool UnknownElemTypeI8) {
333*0fca6ea1SDimitry Andric   Type *Ty = ValueTy;
334*0fca6ea1SDimitry Andric   if (Operand) {
335*0fca6ea1SDimitry Andric     if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
336*0fca6ea1SDimitry Andric       if (Type *NestedTy =
337*0fca6ea1SDimitry Andric               deduceElementTypeHelper(Operand, Visited, UnknownElemTypeI8))
338*0fca6ea1SDimitry Andric         Ty = getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
339*0fca6ea1SDimitry Andric     } else {
340*0fca6ea1SDimitry Andric       Ty = deduceNestedTypeHelper(dyn_cast<User>(Operand), Ty, Visited,
341*0fca6ea1SDimitry Andric                                   UnknownElemTypeI8);
342*0fca6ea1SDimitry Andric     }
343*0fca6ea1SDimitry Andric   }
344*0fca6ea1SDimitry Andric   return Ty;
345*0fca6ea1SDimitry Andric }
346*0fca6ea1SDimitry Andric 
347*0fca6ea1SDimitry Andric // Traverse User instructions to deduce an element pointer type of the operand.
348*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep(
349*0fca6ea1SDimitry Andric     Value *Op, std::unordered_set<Value *> &Visited, bool UnknownElemTypeI8) {
350*0fca6ea1SDimitry Andric   if (!Op || !isPointerTy(Op->getType()))
351*0fca6ea1SDimitry Andric     return nullptr;
352*0fca6ea1SDimitry Andric 
353*0fca6ea1SDimitry Andric   if (auto ElemTy = getPointeeType(Op->getType()))
354*0fca6ea1SDimitry Andric     return ElemTy;
355*0fca6ea1SDimitry Andric 
356*0fca6ea1SDimitry Andric   // maybe we already know operand's element type
357*0fca6ea1SDimitry Andric   if (Type *KnownTy = GR->findDeducedElementType(Op))
358*0fca6ea1SDimitry Andric     return KnownTy;
359*0fca6ea1SDimitry Andric 
360*0fca6ea1SDimitry Andric   for (User *OpU : Op->users()) {
361*0fca6ea1SDimitry Andric     if (Instruction *Inst = dyn_cast<Instruction>(OpU)) {
362*0fca6ea1SDimitry Andric       if (Type *Ty = deduceElementTypeHelper(Inst, Visited, UnknownElemTypeI8))
363*0fca6ea1SDimitry Andric         return Ty;
364*0fca6ea1SDimitry Andric     }
365*0fca6ea1SDimitry Andric   }
366*0fca6ea1SDimitry Andric   return nullptr;
367*0fca6ea1SDimitry Andric }
368*0fca6ea1SDimitry Andric 
369*0fca6ea1SDimitry Andric // Implements what we know in advance about intrinsics and builtin calls
370*0fca6ea1SDimitry Andric // TODO: consider feasibility of this particular case to be generalized by
371*0fca6ea1SDimitry Andric // encoding knowledge about intrinsics and builtin calls by corresponding
372*0fca6ea1SDimitry Andric // specification rules
373*0fca6ea1SDimitry Andric static Type *getPointeeTypeByCallInst(StringRef DemangledName,
374*0fca6ea1SDimitry Andric                                       Function *CalledF, unsigned OpIdx) {
375*0fca6ea1SDimitry Andric   if ((DemangledName.starts_with("__spirv_ocl_printf(") ||
376*0fca6ea1SDimitry Andric        DemangledName.starts_with("printf(")) &&
377*0fca6ea1SDimitry Andric       OpIdx == 0)
378*0fca6ea1SDimitry Andric     return IntegerType::getInt8Ty(CalledF->getContext());
379*0fca6ea1SDimitry Andric   return nullptr;
380*0fca6ea1SDimitry Andric }
381*0fca6ea1SDimitry Andric 
382*0fca6ea1SDimitry Andric // Deduce and return a successfully deduced Type of the Instruction,
383*0fca6ea1SDimitry Andric // or nullptr otherwise.
384*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I,
385*0fca6ea1SDimitry Andric                                                    bool UnknownElemTypeI8) {
386*0fca6ea1SDimitry Andric   std::unordered_set<Value *> Visited;
387*0fca6ea1SDimitry Andric   return deduceElementTypeHelper(I, Visited, UnknownElemTypeI8);
388*0fca6ea1SDimitry Andric }
389*0fca6ea1SDimitry Andric 
390*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::maybeAssignPtrType(Type *&Ty, Value *Op, Type *RefTy,
391*0fca6ea1SDimitry Andric                                              bool UnknownElemTypeI8) {
392*0fca6ea1SDimitry Andric   if (isUntypedPointerTy(RefTy)) {
393*0fca6ea1SDimitry Andric     if (!UnknownElemTypeI8)
394*0fca6ea1SDimitry Andric       return;
395*0fca6ea1SDimitry Andric     if (auto *I = dyn_cast<Instruction>(Op)) {
396*0fca6ea1SDimitry Andric       UncompleteTypeInfo.insert(I);
397*0fca6ea1SDimitry Andric       PostprocessWorklist.push_back(I);
398*0fca6ea1SDimitry Andric     }
399*0fca6ea1SDimitry Andric   }
400*0fca6ea1SDimitry Andric   Ty = RefTy;
401*0fca6ea1SDimitry Andric }
402*0fca6ea1SDimitry Andric 
403*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
404*0fca6ea1SDimitry Andric     Value *I, std::unordered_set<Value *> &Visited, bool UnknownElemTypeI8) {
405*0fca6ea1SDimitry Andric   // allow to pass nullptr as an argument
406*0fca6ea1SDimitry Andric   if (!I)
407*0fca6ea1SDimitry Andric     return nullptr;
408*0fca6ea1SDimitry Andric 
409*0fca6ea1SDimitry Andric   // maybe already known
410*0fca6ea1SDimitry Andric   if (Type *KnownTy = GR->findDeducedElementType(I))
411*0fca6ea1SDimitry Andric     return KnownTy;
412*0fca6ea1SDimitry Andric 
413*0fca6ea1SDimitry Andric   // maybe a cycle
414*0fca6ea1SDimitry Andric   if (Visited.find(I) != Visited.end())
415*0fca6ea1SDimitry Andric     return nullptr;
416*0fca6ea1SDimitry Andric   Visited.insert(I);
417*0fca6ea1SDimitry Andric 
418*0fca6ea1SDimitry Andric   // fallback value in case when we fail to deduce a type
419*0fca6ea1SDimitry Andric   Type *Ty = nullptr;
420*0fca6ea1SDimitry Andric   // look for known basic patterns of type inference
421*0fca6ea1SDimitry Andric   if (auto *Ref = dyn_cast<AllocaInst>(I)) {
422*0fca6ea1SDimitry Andric     maybeAssignPtrType(Ty, I, Ref->getAllocatedType(), UnknownElemTypeI8);
423*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
424*0fca6ea1SDimitry Andric     Ty = Ref->getResultElementType();
425*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<GlobalValue>(I)) {
426*0fca6ea1SDimitry Andric     Ty = deduceElementTypeByValueDeep(
427*0fca6ea1SDimitry Andric         Ref->getValueType(),
428*0fca6ea1SDimitry Andric         Ref->getNumOperands() > 0 ? Ref->getOperand(0) : nullptr, Visited,
429*0fca6ea1SDimitry Andric         UnknownElemTypeI8);
430*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) {
431*0fca6ea1SDimitry Andric     Type *RefTy = deduceElementTypeHelper(Ref->getPointerOperand(), Visited,
432*0fca6ea1SDimitry Andric                                           UnknownElemTypeI8);
433*0fca6ea1SDimitry Andric     maybeAssignPtrType(Ty, I, RefTy, UnknownElemTypeI8);
434*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
435*0fca6ea1SDimitry Andric     if (Type *Src = Ref->getSrcTy(), *Dest = Ref->getDestTy();
436*0fca6ea1SDimitry Andric         isPointerTy(Src) && isPointerTy(Dest))
437*0fca6ea1SDimitry Andric       Ty = deduceElementTypeHelper(Ref->getOperand(0), Visited,
438*0fca6ea1SDimitry Andric                                    UnknownElemTypeI8);
439*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) {
440*0fca6ea1SDimitry Andric     Value *Op = Ref->getNewValOperand();
441*0fca6ea1SDimitry Andric     if (isPointerTy(Op->getType()))
442*0fca6ea1SDimitry Andric       Ty = deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8);
443*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) {
444*0fca6ea1SDimitry Andric     Value *Op = Ref->getValOperand();
445*0fca6ea1SDimitry Andric     if (isPointerTy(Op->getType()))
446*0fca6ea1SDimitry Andric       Ty = deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8);
447*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<PHINode>(I)) {
448*0fca6ea1SDimitry Andric     for (unsigned i = 0; i < Ref->getNumIncomingValues(); i++) {
449*0fca6ea1SDimitry Andric       Ty = deduceElementTypeByUsersDeep(Ref->getIncomingValue(i), Visited,
450*0fca6ea1SDimitry Andric                                         UnknownElemTypeI8);
451*0fca6ea1SDimitry Andric       if (Ty)
452*0fca6ea1SDimitry Andric         break;
453*0fca6ea1SDimitry Andric     }
454*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
455*0fca6ea1SDimitry Andric     for (Value *Op : {Ref->getTrueValue(), Ref->getFalseValue()}) {
456*0fca6ea1SDimitry Andric       Ty = deduceElementTypeByUsersDeep(Op, Visited, UnknownElemTypeI8);
457*0fca6ea1SDimitry Andric       if (Ty)
458*0fca6ea1SDimitry Andric         break;
459*0fca6ea1SDimitry Andric     }
460*0fca6ea1SDimitry Andric   } else if (auto *CI = dyn_cast<CallInst>(I)) {
461*0fca6ea1SDimitry Andric     static StringMap<unsigned> ResTypeByArg = {
462*0fca6ea1SDimitry Andric         {"to_global", 0},
463*0fca6ea1SDimitry Andric         {"to_local", 0},
464*0fca6ea1SDimitry Andric         {"to_private", 0},
465*0fca6ea1SDimitry Andric         {"__spirv_GenericCastToPtr_ToGlobal", 0},
466*0fca6ea1SDimitry Andric         {"__spirv_GenericCastToPtr_ToLocal", 0},
467*0fca6ea1SDimitry Andric         {"__spirv_GenericCastToPtr_ToPrivate", 0},
468*0fca6ea1SDimitry Andric         {"__spirv_GenericCastToPtrExplicit_ToGlobal", 0},
469*0fca6ea1SDimitry Andric         {"__spirv_GenericCastToPtrExplicit_ToLocal", 0},
470*0fca6ea1SDimitry Andric         {"__spirv_GenericCastToPtrExplicit_ToPrivate", 0}};
471*0fca6ea1SDimitry Andric     // TODO: maybe improve performance by caching demangled names
472*0fca6ea1SDimitry Andric     if (Function *CalledF = CI->getCalledFunction()) {
473*0fca6ea1SDimitry Andric       std::string DemangledName =
474*0fca6ea1SDimitry Andric           getOclOrSpirvBuiltinDemangledName(CalledF->getName());
475*0fca6ea1SDimitry Andric       if (DemangledName.length() > 0)
476*0fca6ea1SDimitry Andric         DemangledName = SPIRV::lookupBuiltinNameHelper(DemangledName);
477*0fca6ea1SDimitry Andric       auto AsArgIt = ResTypeByArg.find(DemangledName);
478*0fca6ea1SDimitry Andric       if (AsArgIt != ResTypeByArg.end()) {
479*0fca6ea1SDimitry Andric         Ty = deduceElementTypeHelper(CI->getArgOperand(AsArgIt->second),
480*0fca6ea1SDimitry Andric                                      Visited, UnknownElemTypeI8);
481*0fca6ea1SDimitry Andric       }
482*0fca6ea1SDimitry Andric     }
483*0fca6ea1SDimitry Andric   }
484*0fca6ea1SDimitry Andric 
485*0fca6ea1SDimitry Andric   // remember the found relationship
486*0fca6ea1SDimitry Andric   if (Ty) {
487*0fca6ea1SDimitry Andric     // specify nested types if needed, otherwise return unchanged
488*0fca6ea1SDimitry Andric     GR->addDeducedElementType(I, Ty);
489*0fca6ea1SDimitry Andric   }
490*0fca6ea1SDimitry Andric 
491*0fca6ea1SDimitry Andric   return Ty;
492*0fca6ea1SDimitry Andric }
493*0fca6ea1SDimitry Andric 
494*0fca6ea1SDimitry Andric // Re-create a type of the value if it has untyped pointer fields, also nested.
495*0fca6ea1SDimitry Andric // Return the original value type if no corrections of untyped pointer
496*0fca6ea1SDimitry Andric // information is found or needed.
497*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U,
498*0fca6ea1SDimitry Andric                                                   bool UnknownElemTypeI8) {
499*0fca6ea1SDimitry Andric   std::unordered_set<Value *> Visited;
500*0fca6ea1SDimitry Andric   return deduceNestedTypeHelper(U, U->getType(), Visited, UnknownElemTypeI8);
501*0fca6ea1SDimitry Andric }
502*0fca6ea1SDimitry Andric 
503*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(
504*0fca6ea1SDimitry Andric     User *U, Type *OrigTy, std::unordered_set<Value *> &Visited,
505*0fca6ea1SDimitry Andric     bool UnknownElemTypeI8) {
506*0fca6ea1SDimitry Andric   if (!U)
507*0fca6ea1SDimitry Andric     return OrigTy;
508*0fca6ea1SDimitry Andric 
509*0fca6ea1SDimitry Andric   // maybe already known
510*0fca6ea1SDimitry Andric   if (Type *KnownTy = GR->findDeducedCompositeType(U))
511*0fca6ea1SDimitry Andric     return KnownTy;
512*0fca6ea1SDimitry Andric 
513*0fca6ea1SDimitry Andric   // maybe a cycle
514*0fca6ea1SDimitry Andric   if (Visited.find(U) != Visited.end())
515*0fca6ea1SDimitry Andric     return OrigTy;
516*0fca6ea1SDimitry Andric   Visited.insert(U);
517*0fca6ea1SDimitry Andric 
518*0fca6ea1SDimitry Andric   if (dyn_cast<StructType>(OrigTy)) {
519*0fca6ea1SDimitry Andric     SmallVector<Type *> Tys;
520*0fca6ea1SDimitry Andric     bool Change = false;
521*0fca6ea1SDimitry Andric     for (unsigned i = 0; i < U->getNumOperands(); ++i) {
522*0fca6ea1SDimitry Andric       Value *Op = U->getOperand(i);
523*0fca6ea1SDimitry Andric       Type *OpTy = Op->getType();
524*0fca6ea1SDimitry Andric       Type *Ty = OpTy;
525*0fca6ea1SDimitry Andric       if (Op) {
526*0fca6ea1SDimitry Andric         if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
527*0fca6ea1SDimitry Andric           if (Type *NestedTy =
528*0fca6ea1SDimitry Andric                   deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8))
529*0fca6ea1SDimitry Andric             Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace());
530*0fca6ea1SDimitry Andric         } else {
531*0fca6ea1SDimitry Andric           Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited,
532*0fca6ea1SDimitry Andric                                       UnknownElemTypeI8);
533*0fca6ea1SDimitry Andric         }
534*0fca6ea1SDimitry Andric       }
535*0fca6ea1SDimitry Andric       Tys.push_back(Ty);
536*0fca6ea1SDimitry Andric       Change |= Ty != OpTy;
537*0fca6ea1SDimitry Andric     }
538*0fca6ea1SDimitry Andric     if (Change) {
539*0fca6ea1SDimitry Andric       Type *NewTy = StructType::create(Tys);
540*0fca6ea1SDimitry Andric       GR->addDeducedCompositeType(U, NewTy);
541*0fca6ea1SDimitry Andric       return NewTy;
542*0fca6ea1SDimitry Andric     }
543*0fca6ea1SDimitry Andric   } else if (auto *ArrTy = dyn_cast<ArrayType>(OrigTy)) {
544*0fca6ea1SDimitry Andric     if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) {
545*0fca6ea1SDimitry Andric       Type *OpTy = ArrTy->getElementType();
546*0fca6ea1SDimitry Andric       Type *Ty = OpTy;
547*0fca6ea1SDimitry Andric       if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
548*0fca6ea1SDimitry Andric         if (Type *NestedTy =
549*0fca6ea1SDimitry Andric                 deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8))
550*0fca6ea1SDimitry Andric           Ty = TypedPointerType::get(NestedTy, PtrTy->getAddressSpace());
551*0fca6ea1SDimitry Andric       } else {
552*0fca6ea1SDimitry Andric         Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited,
553*0fca6ea1SDimitry Andric                                     UnknownElemTypeI8);
554*0fca6ea1SDimitry Andric       }
555*0fca6ea1SDimitry Andric       if (Ty != OpTy) {
556*0fca6ea1SDimitry Andric         Type *NewTy = ArrayType::get(Ty, ArrTy->getNumElements());
557*0fca6ea1SDimitry Andric         GR->addDeducedCompositeType(U, NewTy);
558*0fca6ea1SDimitry Andric         return NewTy;
559*0fca6ea1SDimitry Andric       }
560*0fca6ea1SDimitry Andric     }
561*0fca6ea1SDimitry Andric   } else if (auto *VecTy = dyn_cast<VectorType>(OrigTy)) {
562*0fca6ea1SDimitry Andric     if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) {
563*0fca6ea1SDimitry Andric       Type *OpTy = VecTy->getElementType();
564*0fca6ea1SDimitry Andric       Type *Ty = OpTy;
565*0fca6ea1SDimitry Andric       if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
566*0fca6ea1SDimitry Andric         if (Type *NestedTy =
567*0fca6ea1SDimitry Andric                 deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8))
568*0fca6ea1SDimitry Andric           Ty = getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
569*0fca6ea1SDimitry Andric       } else {
570*0fca6ea1SDimitry Andric         Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited,
571*0fca6ea1SDimitry Andric                                     UnknownElemTypeI8);
572*0fca6ea1SDimitry Andric       }
573*0fca6ea1SDimitry Andric       if (Ty != OpTy) {
574*0fca6ea1SDimitry Andric         Type *NewTy = VectorType::get(Ty, VecTy->getElementCount());
575*0fca6ea1SDimitry Andric         GR->addDeducedCompositeType(U, NewTy);
576*0fca6ea1SDimitry Andric         return NewTy;
577*0fca6ea1SDimitry Andric       }
578*0fca6ea1SDimitry Andric     }
579*0fca6ea1SDimitry Andric   }
580*0fca6ea1SDimitry Andric 
581*0fca6ea1SDimitry Andric   return OrigTy;
582*0fca6ea1SDimitry Andric }
583*0fca6ea1SDimitry Andric 
584*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceElementType(Value *I, bool UnknownElemTypeI8) {
585*0fca6ea1SDimitry Andric   if (Type *Ty = deduceElementTypeHelper(I, UnknownElemTypeI8))
586*0fca6ea1SDimitry Andric     return Ty;
587*0fca6ea1SDimitry Andric   if (!UnknownElemTypeI8)
588*0fca6ea1SDimitry Andric     return nullptr;
589*0fca6ea1SDimitry Andric   if (auto *Instr = dyn_cast<Instruction>(I)) {
590*0fca6ea1SDimitry Andric     UncompleteTypeInfo.insert(Instr);
591*0fca6ea1SDimitry Andric     PostprocessWorklist.push_back(Instr);
592*0fca6ea1SDimitry Andric   }
593*0fca6ea1SDimitry Andric   return IntegerType::getInt8Ty(I->getContext());
594*0fca6ea1SDimitry Andric }
595*0fca6ea1SDimitry Andric 
596*0fca6ea1SDimitry Andric static inline Type *getAtomicElemTy(SPIRVGlobalRegistry *GR, Instruction *I,
597*0fca6ea1SDimitry Andric                                     Value *PointerOperand) {
598*0fca6ea1SDimitry Andric   Type *PointeeTy = GR->findDeducedElementType(PointerOperand);
599*0fca6ea1SDimitry Andric   if (PointeeTy && !isUntypedPointerTy(PointeeTy))
600*0fca6ea1SDimitry Andric     return nullptr;
601*0fca6ea1SDimitry Andric   auto *PtrTy = dyn_cast<PointerType>(I->getType());
602*0fca6ea1SDimitry Andric   if (!PtrTy)
603*0fca6ea1SDimitry Andric     return I->getType();
604*0fca6ea1SDimitry Andric   if (Type *NestedTy = GR->findDeducedElementType(I))
605*0fca6ea1SDimitry Andric     return getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
606*0fca6ea1SDimitry Andric   return nullptr;
607*0fca6ea1SDimitry Andric }
608*0fca6ea1SDimitry Andric 
609*0fca6ea1SDimitry Andric // If the Instruction has Pointer operands with unresolved types, this function
610*0fca6ea1SDimitry Andric // tries to deduce them. If the Instruction has Pointer operands with known
611*0fca6ea1SDimitry Andric // types which differ from expected, this function tries to insert a bitcast to
612*0fca6ea1SDimitry Andric // resolve the issue.
613*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::deduceOperandElementType(Instruction *I,
614*0fca6ea1SDimitry Andric                                                    Instruction *AskOp,
615*0fca6ea1SDimitry Andric                                                    Type *AskTy,
616*0fca6ea1SDimitry Andric                                                    CallInst *AskCI) {
617*0fca6ea1SDimitry Andric   SmallVector<std::pair<Value *, unsigned>> Ops;
618*0fca6ea1SDimitry Andric   Type *KnownElemTy = nullptr;
619*0fca6ea1SDimitry Andric   // look for known basic patterns of type inference
620*0fca6ea1SDimitry Andric   if (auto *Ref = dyn_cast<PHINode>(I)) {
621*0fca6ea1SDimitry Andric     if (!isPointerTy(I->getType()) ||
622*0fca6ea1SDimitry Andric         !(KnownElemTy = GR->findDeducedElementType(I)))
623*0fca6ea1SDimitry Andric       return;
624*0fca6ea1SDimitry Andric     for (unsigned i = 0; i < Ref->getNumIncomingValues(); i++) {
625*0fca6ea1SDimitry Andric       Value *Op = Ref->getIncomingValue(i);
626*0fca6ea1SDimitry Andric       if (isPointerTy(Op->getType()))
627*0fca6ea1SDimitry Andric         Ops.push_back(std::make_pair(Op, i));
628*0fca6ea1SDimitry Andric     }
629*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) {
630*0fca6ea1SDimitry Andric     KnownElemTy = GR->findDeducedElementType(I);
631*0fca6ea1SDimitry Andric     if (!KnownElemTy)
632*0fca6ea1SDimitry Andric       return;
633*0fca6ea1SDimitry Andric     Ops.push_back(std::make_pair(Ref->getPointerOperand(), 0));
634*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
635*0fca6ea1SDimitry Andric     KnownElemTy = Ref->getSourceElementType();
636*0fca6ea1SDimitry Andric     if (isUntypedPointerTy(KnownElemTy))
637*0fca6ea1SDimitry Andric       return;
638*0fca6ea1SDimitry Andric     Type *PointeeTy = GR->findDeducedElementType(Ref->getPointerOperand());
639*0fca6ea1SDimitry Andric     if (PointeeTy && !isUntypedPointerTy(PointeeTy))
640*0fca6ea1SDimitry Andric       return;
641*0fca6ea1SDimitry Andric     Ops.push_back(std::make_pair(Ref->getPointerOperand(),
642*0fca6ea1SDimitry Andric                                  GetElementPtrInst::getPointerOperandIndex()));
643*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<LoadInst>(I)) {
644*0fca6ea1SDimitry Andric     KnownElemTy = I->getType();
645*0fca6ea1SDimitry Andric     if (isUntypedPointerTy(KnownElemTy))
646*0fca6ea1SDimitry Andric       return;
647*0fca6ea1SDimitry Andric     Type *PointeeTy = GR->findDeducedElementType(Ref->getPointerOperand());
648*0fca6ea1SDimitry Andric     if (PointeeTy && !isUntypedPointerTy(PointeeTy))
649*0fca6ea1SDimitry Andric       return;
650*0fca6ea1SDimitry Andric     Ops.push_back(std::make_pair(Ref->getPointerOperand(),
651*0fca6ea1SDimitry Andric                                  LoadInst::getPointerOperandIndex()));
652*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<StoreInst>(I)) {
653*0fca6ea1SDimitry Andric     if (IsKernelArgInt8(Ref->getParent()->getParent(), Ref))
654*0fca6ea1SDimitry Andric       return;
655*0fca6ea1SDimitry Andric     if (!(KnownElemTy = reconstructType(GR, Ref->getValueOperand())))
656*0fca6ea1SDimitry Andric       return;
657*0fca6ea1SDimitry Andric     Type *PointeeTy = GR->findDeducedElementType(Ref->getPointerOperand());
658*0fca6ea1SDimitry Andric     if (PointeeTy && !isUntypedPointerTy(PointeeTy))
659*0fca6ea1SDimitry Andric       return;
660*0fca6ea1SDimitry Andric     Ops.push_back(std::make_pair(Ref->getPointerOperand(),
661*0fca6ea1SDimitry Andric                                  StoreInst::getPointerOperandIndex()));
662*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) {
663*0fca6ea1SDimitry Andric     KnownElemTy = getAtomicElemTy(GR, I, Ref->getPointerOperand());
664*0fca6ea1SDimitry Andric     if (!KnownElemTy)
665*0fca6ea1SDimitry Andric       return;
666*0fca6ea1SDimitry Andric     Ops.push_back(std::make_pair(Ref->getPointerOperand(),
667*0fca6ea1SDimitry Andric                                  AtomicCmpXchgInst::getPointerOperandIndex()));
668*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) {
669*0fca6ea1SDimitry Andric     KnownElemTy = getAtomicElemTy(GR, I, Ref->getPointerOperand());
670*0fca6ea1SDimitry Andric     if (!KnownElemTy)
671*0fca6ea1SDimitry Andric       return;
672*0fca6ea1SDimitry Andric     Ops.push_back(std::make_pair(Ref->getPointerOperand(),
673*0fca6ea1SDimitry Andric                                  AtomicRMWInst::getPointerOperandIndex()));
674*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
675*0fca6ea1SDimitry Andric     if (!isPointerTy(I->getType()) ||
676*0fca6ea1SDimitry Andric         !(KnownElemTy = GR->findDeducedElementType(I)))
677*0fca6ea1SDimitry Andric       return;
678*0fca6ea1SDimitry Andric     for (unsigned i = 0; i < Ref->getNumOperands(); i++) {
679*0fca6ea1SDimitry Andric       Value *Op = Ref->getOperand(i);
680*0fca6ea1SDimitry Andric       if (isPointerTy(Op->getType()))
681*0fca6ea1SDimitry Andric         Ops.push_back(std::make_pair(Op, i));
682*0fca6ea1SDimitry Andric     }
683*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<ReturnInst>(I)) {
684*0fca6ea1SDimitry Andric     Type *RetTy = F->getReturnType();
685*0fca6ea1SDimitry Andric     if (!isPointerTy(RetTy))
686*0fca6ea1SDimitry Andric       return;
687*0fca6ea1SDimitry Andric     Value *Op = Ref->getReturnValue();
688*0fca6ea1SDimitry Andric     if (!Op)
689*0fca6ea1SDimitry Andric       return;
690*0fca6ea1SDimitry Andric     if (!(KnownElemTy = GR->findDeducedElementType(F))) {
691*0fca6ea1SDimitry Andric       if (Type *OpElemTy = GR->findDeducedElementType(Op)) {
692*0fca6ea1SDimitry Andric         GR->addDeducedElementType(F, OpElemTy);
693*0fca6ea1SDimitry Andric         TypedPointerType *DerivedTy =
694*0fca6ea1SDimitry Andric             TypedPointerType::get(OpElemTy, getPointerAddressSpace(RetTy));
695*0fca6ea1SDimitry Andric         GR->addReturnType(F, DerivedTy);
696*0fca6ea1SDimitry Andric       }
697*0fca6ea1SDimitry Andric       return;
698*0fca6ea1SDimitry Andric     }
699*0fca6ea1SDimitry Andric     Ops.push_back(std::make_pair(Op, 0));
700*0fca6ea1SDimitry Andric   } else if (auto *Ref = dyn_cast<ICmpInst>(I)) {
701*0fca6ea1SDimitry Andric     if (!isPointerTy(Ref->getOperand(0)->getType()))
702*0fca6ea1SDimitry Andric       return;
703*0fca6ea1SDimitry Andric     Value *Op0 = Ref->getOperand(0);
704*0fca6ea1SDimitry Andric     Value *Op1 = Ref->getOperand(1);
705*0fca6ea1SDimitry Andric     Type *ElemTy0 = GR->findDeducedElementType(Op0);
706*0fca6ea1SDimitry Andric     Type *ElemTy1 = GR->findDeducedElementType(Op1);
707*0fca6ea1SDimitry Andric     if (ElemTy0) {
708*0fca6ea1SDimitry Andric       KnownElemTy = ElemTy0;
709*0fca6ea1SDimitry Andric       Ops.push_back(std::make_pair(Op1, 1));
710*0fca6ea1SDimitry Andric     } else if (ElemTy1) {
711*0fca6ea1SDimitry Andric       KnownElemTy = ElemTy1;
712*0fca6ea1SDimitry Andric       Ops.push_back(std::make_pair(Op0, 0));
713*0fca6ea1SDimitry Andric     }
714*0fca6ea1SDimitry Andric   } else if (auto *CI = dyn_cast<CallInst>(I)) {
715*0fca6ea1SDimitry Andric     if (Function *CalledF = CI->getCalledFunction()) {
716*0fca6ea1SDimitry Andric       std::string DemangledName =
717*0fca6ea1SDimitry Andric           getOclOrSpirvBuiltinDemangledName(CalledF->getName());
718*0fca6ea1SDimitry Andric       if (DemangledName.length() > 0 &&
719*0fca6ea1SDimitry Andric           !StringRef(DemangledName).starts_with("llvm.")) {
720*0fca6ea1SDimitry Andric         auto [Grp, Opcode, ExtNo] =
721*0fca6ea1SDimitry Andric             SPIRV::mapBuiltinToOpcode(DemangledName, InstrSet);
722*0fca6ea1SDimitry Andric         if (Opcode == SPIRV::OpGroupAsyncCopy) {
723*0fca6ea1SDimitry Andric           for (unsigned i = 0, PtrCnt = 0; i < CI->arg_size() && PtrCnt < 2;
724*0fca6ea1SDimitry Andric                ++i) {
725*0fca6ea1SDimitry Andric             Value *Op = CI->getArgOperand(i);
726*0fca6ea1SDimitry Andric             if (!isPointerTy(Op->getType()))
727*0fca6ea1SDimitry Andric               continue;
728*0fca6ea1SDimitry Andric             ++PtrCnt;
729*0fca6ea1SDimitry Andric             if (Type *ElemTy = GR->findDeducedElementType(Op))
730*0fca6ea1SDimitry Andric               KnownElemTy = ElemTy; // src will rewrite dest if both are defined
731*0fca6ea1SDimitry Andric             Ops.push_back(std::make_pair(Op, i));
732*0fca6ea1SDimitry Andric           }
733*0fca6ea1SDimitry Andric         } else if (Grp == SPIRV::Atomic || Grp == SPIRV::AtomicFloating) {
734*0fca6ea1SDimitry Andric           if (CI->arg_size() < 2)
735*0fca6ea1SDimitry Andric             return;
736*0fca6ea1SDimitry Andric           Value *Op = CI->getArgOperand(0);
737*0fca6ea1SDimitry Andric           if (!isPointerTy(Op->getType()))
738*0fca6ea1SDimitry Andric             return;
739*0fca6ea1SDimitry Andric           switch (Opcode) {
740*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicLoad:
741*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicCompareExchangeWeak:
742*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicCompareExchange:
743*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicExchange:
744*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicIAdd:
745*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicISub:
746*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicOr:
747*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicXor:
748*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicAnd:
749*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicUMin:
750*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicUMax:
751*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicSMin:
752*0fca6ea1SDimitry Andric           case SPIRV::OpAtomicSMax: {
753*0fca6ea1SDimitry Andric             KnownElemTy = getAtomicElemTy(GR, I, Op);
754*0fca6ea1SDimitry Andric             if (!KnownElemTy)
755*0fca6ea1SDimitry Andric               return;
756*0fca6ea1SDimitry Andric             Ops.push_back(std::make_pair(Op, 0));
757*0fca6ea1SDimitry Andric           } break;
758*0fca6ea1SDimitry Andric           }
759*0fca6ea1SDimitry Andric         }
760*0fca6ea1SDimitry Andric       }
761*0fca6ea1SDimitry Andric     }
762*0fca6ea1SDimitry Andric   }
763*0fca6ea1SDimitry Andric 
764*0fca6ea1SDimitry Andric   // There is no enough info to deduce types or all is valid.
765*0fca6ea1SDimitry Andric   if (!KnownElemTy || Ops.size() == 0)
766*0fca6ea1SDimitry Andric     return;
767*0fca6ea1SDimitry Andric 
768*0fca6ea1SDimitry Andric   LLVMContext &Ctx = F->getContext();
769*0fca6ea1SDimitry Andric   IRBuilder<> B(Ctx);
770*0fca6ea1SDimitry Andric   for (auto &OpIt : Ops) {
771*0fca6ea1SDimitry Andric     Value *Op = OpIt.first;
772*0fca6ea1SDimitry Andric     if (Op->use_empty() || (AskOp && Op != AskOp))
773*0fca6ea1SDimitry Andric       continue;
774*0fca6ea1SDimitry Andric     Type *Ty = AskOp ? AskTy : GR->findDeducedElementType(Op);
775*0fca6ea1SDimitry Andric     if (Ty == KnownElemTy)
776*0fca6ea1SDimitry Andric       continue;
777*0fca6ea1SDimitry Andric     Value *OpTyVal = PoisonValue::get(KnownElemTy);
778*0fca6ea1SDimitry Andric     Type *OpTy = Op->getType();
779*0fca6ea1SDimitry Andric     if (!Ty || AskTy || isUntypedPointerTy(Ty) ||
780*0fca6ea1SDimitry Andric         UncompleteTypeInfo.contains(Op)) {
781*0fca6ea1SDimitry Andric       GR->addDeducedElementType(Op, KnownElemTy);
782*0fca6ea1SDimitry Andric       // check if there is existing Intrinsic::spv_assign_ptr_type instruction
783*0fca6ea1SDimitry Andric       CallInst *AssignCI = AskCI ? AskCI : GR->findAssignPtrTypeInstr(Op);
784*0fca6ea1SDimitry Andric       if (AssignCI == nullptr) {
785*0fca6ea1SDimitry Andric         Instruction *User = dyn_cast<Instruction>(Op->use_begin()->get());
786*0fca6ea1SDimitry Andric         setInsertPointSkippingPhis(B, User ? User->getNextNode() : I);
787*0fca6ea1SDimitry Andric         CallInst *CI =
788*0fca6ea1SDimitry Andric             buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {OpTy}, OpTyVal, Op,
789*0fca6ea1SDimitry Andric                             {B.getInt32(getPointerAddressSpace(OpTy))}, B);
790*0fca6ea1SDimitry Andric         GR->addAssignPtrTypeInstr(Op, CI);
791*0fca6ea1SDimitry Andric       } else {
792*0fca6ea1SDimitry Andric         updateAssignType(AssignCI, Op, OpTyVal);
793*0fca6ea1SDimitry Andric       }
794*0fca6ea1SDimitry Andric     } else {
795*0fca6ea1SDimitry Andric       if (auto *OpI = dyn_cast<Instruction>(Op)) {
796*0fca6ea1SDimitry Andric         // spv_ptrcast's argument Op denotes an instruction that generates
797*0fca6ea1SDimitry Andric         // a value, and we may use getInsertionPointAfterDef()
798*0fca6ea1SDimitry Andric         B.SetInsertPoint(*OpI->getInsertionPointAfterDef());
799*0fca6ea1SDimitry Andric         B.SetCurrentDebugLocation(OpI->getDebugLoc());
800*0fca6ea1SDimitry Andric       } else if (auto *OpA = dyn_cast<Argument>(Op)) {
801*0fca6ea1SDimitry Andric         B.SetInsertPointPastAllocas(OpA->getParent());
802*0fca6ea1SDimitry Andric         B.SetCurrentDebugLocation(DebugLoc());
803*0fca6ea1SDimitry Andric       } else {
804*0fca6ea1SDimitry Andric         B.SetInsertPoint(F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
805*0fca6ea1SDimitry Andric       }
806*0fca6ea1SDimitry Andric       SmallVector<Type *, 2> Types = {OpTy, OpTy};
807*0fca6ea1SDimitry Andric       SmallVector<Value *, 2> Args = {Op, buildMD(OpTyVal),
808*0fca6ea1SDimitry Andric                                       B.getInt32(getPointerAddressSpace(OpTy))};
809*0fca6ea1SDimitry Andric       CallInst *PtrCastI =
810*0fca6ea1SDimitry Andric           B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
811*0fca6ea1SDimitry Andric       I->setOperand(OpIt.second, PtrCastI);
812*0fca6ea1SDimitry Andric     }
813*0fca6ea1SDimitry Andric   }
814*0fca6ea1SDimitry Andric }
815*0fca6ea1SDimitry Andric 
81681ad6265SDimitry Andric void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old,
817*0fca6ea1SDimitry Andric                                               Instruction *New,
818*0fca6ea1SDimitry Andric                                               IRBuilder<> &B) {
81981ad6265SDimitry Andric   while (!Old->user_empty()) {
82081ad6265SDimitry Andric     auto *U = Old->user_back();
821fcaf7f86SDimitry Andric     if (isAssignTypeInstr(U)) {
822*0fca6ea1SDimitry Andric       B.SetInsertPoint(U);
82381ad6265SDimitry Andric       SmallVector<Value *, 2> Args = {New, U->getOperand(1)};
824*0fca6ea1SDimitry Andric       CallInst *AssignCI =
825*0fca6ea1SDimitry Andric           B.CreateIntrinsic(Intrinsic::spv_assign_type, {New->getType()}, Args);
826*0fca6ea1SDimitry Andric       GR->addAssignPtrTypeInstr(New, AssignCI);
82781ad6265SDimitry Andric       U->eraseFromParent();
828fcaf7f86SDimitry Andric     } else if (isMemInstrToReplace(U) || isa<ReturnInst>(U) ||
829fcaf7f86SDimitry Andric                isa<CallInst>(U)) {
830fcaf7f86SDimitry Andric       U->replaceUsesOfWith(Old, New);
83181ad6265SDimitry Andric     } else {
83281ad6265SDimitry Andric       llvm_unreachable("illegal aggregate intrinsic user");
83381ad6265SDimitry Andric     }
83481ad6265SDimitry Andric   }
83581ad6265SDimitry Andric   Old->eraseFromParent();
83681ad6265SDimitry Andric }
83781ad6265SDimitry Andric 
838*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::preprocessUndefs(IRBuilder<> &B) {
83906c3fb27SDimitry Andric   std::queue<Instruction *> Worklist;
84006c3fb27SDimitry Andric   for (auto &I : instructions(F))
84106c3fb27SDimitry Andric     Worklist.push(&I);
84206c3fb27SDimitry Andric 
84306c3fb27SDimitry Andric   while (!Worklist.empty()) {
84406c3fb27SDimitry Andric     Instruction *I = Worklist.front();
845*0fca6ea1SDimitry Andric     bool BPrepared = false;
84606c3fb27SDimitry Andric     Worklist.pop();
84706c3fb27SDimitry Andric 
84806c3fb27SDimitry Andric     for (auto &Op : I->operands()) {
84906c3fb27SDimitry Andric       auto *AggrUndef = dyn_cast<UndefValue>(Op);
85006c3fb27SDimitry Andric       if (!AggrUndef || !Op->getType()->isAggregateType())
85106c3fb27SDimitry Andric         continue;
85206c3fb27SDimitry Andric 
853*0fca6ea1SDimitry Andric       if (!BPrepared) {
854*0fca6ea1SDimitry Andric         setInsertPointSkippingPhis(B, I);
855*0fca6ea1SDimitry Andric         BPrepared = true;
856*0fca6ea1SDimitry Andric       }
857*0fca6ea1SDimitry Andric       auto *IntrUndef = B.CreateIntrinsic(Intrinsic::spv_undef, {}, {});
85806c3fb27SDimitry Andric       Worklist.push(IntrUndef);
85906c3fb27SDimitry Andric       I->replaceUsesOfWith(Op, IntrUndef);
86006c3fb27SDimitry Andric       AggrConsts[IntrUndef] = AggrUndef;
861*0fca6ea1SDimitry Andric       AggrConstTypes[IntrUndef] = AggrUndef->getType();
86206c3fb27SDimitry Andric     }
86306c3fb27SDimitry Andric   }
86406c3fb27SDimitry Andric }
86506c3fb27SDimitry Andric 
866*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) {
86781ad6265SDimitry Andric   std::queue<Instruction *> Worklist;
86881ad6265SDimitry Andric   for (auto &I : instructions(F))
86981ad6265SDimitry Andric     Worklist.push(&I);
87081ad6265SDimitry Andric 
87181ad6265SDimitry Andric   while (!Worklist.empty()) {
87281ad6265SDimitry Andric     auto *I = Worklist.front();
873*0fca6ea1SDimitry Andric     bool IsPhi = isa<PHINode>(I), BPrepared = false;
87481ad6265SDimitry Andric     assert(I);
87581ad6265SDimitry Andric     bool KeepInst = false;
87681ad6265SDimitry Andric     for (const auto &Op : I->operands()) {
877*0fca6ea1SDimitry Andric       Constant *AggrConst = nullptr;
878*0fca6ea1SDimitry Andric       Type *ResTy = nullptr;
879*0fca6ea1SDimitry Andric       if (auto *COp = dyn_cast<ConstantVector>(Op)) {
880*0fca6ea1SDimitry Andric         AggrConst = cast<Constant>(COp);
881*0fca6ea1SDimitry Andric         ResTy = COp->getType();
882*0fca6ea1SDimitry Andric       } else if (auto *COp = dyn_cast<ConstantArray>(Op)) {
883*0fca6ea1SDimitry Andric         AggrConst = cast<Constant>(COp);
884*0fca6ea1SDimitry Andric         ResTy = B.getInt32Ty();
885*0fca6ea1SDimitry Andric       } else if (auto *COp = dyn_cast<ConstantStruct>(Op)) {
886*0fca6ea1SDimitry Andric         AggrConst = cast<Constant>(COp);
887*0fca6ea1SDimitry Andric         ResTy = B.getInt32Ty();
888*0fca6ea1SDimitry Andric       } else if (auto *COp = dyn_cast<ConstantDataArray>(Op)) {
889*0fca6ea1SDimitry Andric         AggrConst = cast<Constant>(COp);
890*0fca6ea1SDimitry Andric         ResTy = B.getInt32Ty();
891*0fca6ea1SDimitry Andric       } else if (auto *COp = dyn_cast<ConstantAggregateZero>(Op)) {
892*0fca6ea1SDimitry Andric         AggrConst = cast<Constant>(COp);
893*0fca6ea1SDimitry Andric         ResTy = Op->getType()->isVectorTy() ? COp->getType() : B.getInt32Ty();
894*0fca6ea1SDimitry Andric       }
895*0fca6ea1SDimitry Andric       if (AggrConst) {
89681ad6265SDimitry Andric         SmallVector<Value *> Args;
897*0fca6ea1SDimitry Andric         if (auto *COp = dyn_cast<ConstantDataSequential>(Op))
898*0fca6ea1SDimitry Andric           for (unsigned i = 0; i < COp->getNumElements(); ++i)
899*0fca6ea1SDimitry Andric             Args.push_back(COp->getElementAsConstant(i));
900*0fca6ea1SDimitry Andric         else
901*0fca6ea1SDimitry Andric           for (auto &COp : AggrConst->operands())
902*0fca6ea1SDimitry Andric             Args.push_back(COp);
903*0fca6ea1SDimitry Andric         if (!BPrepared) {
904*0fca6ea1SDimitry Andric           IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
905*0fca6ea1SDimitry Andric                 : B.SetInsertPoint(I);
906*0fca6ea1SDimitry Andric           BPrepared = true;
907*0fca6ea1SDimitry Andric         }
908*0fca6ea1SDimitry Andric         auto *CI =
909*0fca6ea1SDimitry Andric             B.CreateIntrinsic(Intrinsic::spv_const_composite, {ResTy}, {Args});
910*0fca6ea1SDimitry Andric         Worklist.push(CI);
911*0fca6ea1SDimitry Andric         I->replaceUsesOfWith(Op, CI);
912*0fca6ea1SDimitry Andric         KeepInst = true;
913*0fca6ea1SDimitry Andric         AggrConsts[CI] = AggrConst;
914*0fca6ea1SDimitry Andric         AggrConstTypes[CI] = deduceNestedTypeHelper(AggrConst, false);
91581ad6265SDimitry Andric       }
91681ad6265SDimitry Andric     }
91781ad6265SDimitry Andric     if (!KeepInst)
91881ad6265SDimitry Andric       Worklist.pop();
91981ad6265SDimitry Andric   }
92081ad6265SDimitry Andric }
92181ad6265SDimitry Andric 
922*0fca6ea1SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
923*0fca6ea1SDimitry Andric   if (!Call.isInlineAsm())
924*0fca6ea1SDimitry Andric     return &Call;
925*0fca6ea1SDimitry Andric 
926*0fca6ea1SDimitry Andric   const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
927*0fca6ea1SDimitry Andric   LLVMContext &Ctx = F->getContext();
928*0fca6ea1SDimitry Andric 
929*0fca6ea1SDimitry Andric   Constant *TyC = UndefValue::get(IA->getFunctionType());
930*0fca6ea1SDimitry Andric   MDString *ConstraintString = MDString::get(Ctx, IA->getConstraintString());
931*0fca6ea1SDimitry Andric   SmallVector<Value *> Args = {
932*0fca6ea1SDimitry Andric       buildMD(TyC),
933*0fca6ea1SDimitry Andric       MetadataAsValue::get(Ctx, MDNode::get(Ctx, ConstraintString))};
934*0fca6ea1SDimitry Andric   for (unsigned OpIdx = 0; OpIdx < Call.arg_size(); OpIdx++)
935*0fca6ea1SDimitry Andric     Args.push_back(Call.getArgOperand(OpIdx));
936*0fca6ea1SDimitry Andric 
937*0fca6ea1SDimitry Andric   IRBuilder<> B(Call.getParent());
938*0fca6ea1SDimitry Andric   B.SetInsertPoint(&Call);
939*0fca6ea1SDimitry Andric   B.CreateIntrinsic(Intrinsic::spv_inline_asm, {}, {Args});
940*0fca6ea1SDimitry Andric   return &Call;
941*0fca6ea1SDimitry Andric }
942*0fca6ea1SDimitry Andric 
94381ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitSwitchInst(SwitchInst &I) {
944*0fca6ea1SDimitry Andric   BasicBlock *ParentBB = I.getParent();
945*0fca6ea1SDimitry Andric   IRBuilder<> B(ParentBB);
946*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
94781ad6265SDimitry Andric   SmallVector<Value *, 4> Args;
948*0fca6ea1SDimitry Andric   SmallVector<BasicBlock *> BBCases;
949*0fca6ea1SDimitry Andric   for (auto &Op : I.operands()) {
950*0fca6ea1SDimitry Andric     if (Op.get()->getType()->isSized()) {
95181ad6265SDimitry Andric       Args.push_back(Op);
952*0fca6ea1SDimitry Andric     } else if (BasicBlock *BB = dyn_cast<BasicBlock>(Op.get())) {
953*0fca6ea1SDimitry Andric       BBCases.push_back(BB);
954*0fca6ea1SDimitry Andric       Args.push_back(BlockAddress::get(BB->getParent(), BB));
955*0fca6ea1SDimitry Andric     } else {
956*0fca6ea1SDimitry Andric       report_fatal_error("Unexpected switch operand");
957*0fca6ea1SDimitry Andric     }
958*0fca6ea1SDimitry Andric   }
959*0fca6ea1SDimitry Andric   CallInst *NewI = B.CreateIntrinsic(Intrinsic::spv_switch,
960*0fca6ea1SDimitry Andric                                      {I.getOperand(0)->getType()}, {Args});
961*0fca6ea1SDimitry Andric   // remove switch to avoid its unneeded and undesirable unwrap into branches
962*0fca6ea1SDimitry Andric   // and conditions
963*0fca6ea1SDimitry Andric   I.replaceAllUsesWith(NewI);
964*0fca6ea1SDimitry Andric   I.eraseFromParent();
965*0fca6ea1SDimitry Andric   // insert artificial and temporary instruction to preserve valid CFG,
966*0fca6ea1SDimitry Andric   // it will be removed after IR translation pass
967*0fca6ea1SDimitry Andric   B.SetInsertPoint(ParentBB);
968*0fca6ea1SDimitry Andric   IndirectBrInst *BrI = B.CreateIndirectBr(
969*0fca6ea1SDimitry Andric       Constant::getNullValue(PointerType::getUnqual(ParentBB->getContext())),
970*0fca6ea1SDimitry Andric       BBCases.size());
971*0fca6ea1SDimitry Andric   for (BasicBlock *BBCase : BBCases)
972*0fca6ea1SDimitry Andric     BrI->addDestination(BBCase);
973*0fca6ea1SDimitry Andric   return BrI;
97481ad6265SDimitry Andric }
97581ad6265SDimitry Andric 
97681ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) {
977*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
978*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
97981ad6265SDimitry Andric   SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
98081ad6265SDimitry Andric   SmallVector<Value *, 4> Args;
981*0fca6ea1SDimitry Andric   Args.push_back(B.getInt1(I.isInBounds()));
98281ad6265SDimitry Andric   for (auto &Op : I.operands())
98381ad6265SDimitry Andric     Args.push_back(Op);
984*0fca6ea1SDimitry Andric   auto *NewI = B.CreateIntrinsic(Intrinsic::spv_gep, {Types}, {Args});
98581ad6265SDimitry Andric   I.replaceAllUsesWith(NewI);
98681ad6265SDimitry Andric   I.eraseFromParent();
98781ad6265SDimitry Andric   return NewI;
98881ad6265SDimitry Andric }
98981ad6265SDimitry Andric 
99081ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
991*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
992*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
9931db9f3b2SDimitry Andric   Value *Source = I.getOperand(0);
9941db9f3b2SDimitry Andric 
9951db9f3b2SDimitry Andric   // SPIR-V, contrary to LLVM 17+ IR, supports bitcasts between pointers of
9961db9f3b2SDimitry Andric   // varying element types. In case of IR coming from older versions of LLVM
9971db9f3b2SDimitry Andric   // such bitcasts do not provide sufficient information, should be just skipped
998*0fca6ea1SDimitry Andric   // here, and handled in insertPtrCastOrAssignTypeInstr.
999*0fca6ea1SDimitry Andric   if (isPointerTy(I.getType())) {
10001db9f3b2SDimitry Andric     I.replaceAllUsesWith(Source);
10011db9f3b2SDimitry Andric     I.eraseFromParent();
10021db9f3b2SDimitry Andric     return nullptr;
10031db9f3b2SDimitry Andric   }
10041db9f3b2SDimitry Andric 
10051db9f3b2SDimitry Andric   SmallVector<Type *, 2> Types = {I.getType(), Source->getType()};
100681ad6265SDimitry Andric   SmallVector<Value *> Args(I.op_begin(), I.op_end());
1007*0fca6ea1SDimitry Andric   auto *NewI = B.CreateIntrinsic(Intrinsic::spv_bitcast, {Types}, {Args});
100881ad6265SDimitry Andric   std::string InstName = I.hasName() ? I.getName().str() : "";
100981ad6265SDimitry Andric   I.replaceAllUsesWith(NewI);
101081ad6265SDimitry Andric   I.eraseFromParent();
101181ad6265SDimitry Andric   NewI->setName(InstName);
101281ad6265SDimitry Andric   return NewI;
101381ad6265SDimitry Andric }
101481ad6265SDimitry Andric 
1015*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::insertAssignPtrTypeTargetExt(
1016*0fca6ea1SDimitry Andric     TargetExtType *AssignedType, Value *V, IRBuilder<> &B) {
1017*0fca6ea1SDimitry Andric   Type *VTy = V->getType();
1018*0fca6ea1SDimitry Andric 
1019*0fca6ea1SDimitry Andric   // A couple of sanity checks.
1020*0fca6ea1SDimitry Andric   assert(isPointerTy(VTy) && "Expect a pointer type!");
1021*0fca6ea1SDimitry Andric   if (auto PType = dyn_cast<TypedPointerType>(VTy))
1022*0fca6ea1SDimitry Andric     if (PType->getElementType() != AssignedType)
1023*0fca6ea1SDimitry Andric       report_fatal_error("Unexpected pointer element type!");
1024*0fca6ea1SDimitry Andric 
1025*0fca6ea1SDimitry Andric   CallInst *AssignCI = GR->findAssignPtrTypeInstr(V);
1026*0fca6ea1SDimitry Andric   if (!AssignCI) {
1027*0fca6ea1SDimitry Andric     buildAssignType(B, AssignedType, V);
10281db9f3b2SDimitry Andric     return;
10291db9f3b2SDimitry Andric   }
10301db9f3b2SDimitry Andric 
1031*0fca6ea1SDimitry Andric   Type *CurrentType =
1032*0fca6ea1SDimitry Andric       dyn_cast<ConstantAsMetadata>(
1033*0fca6ea1SDimitry Andric           cast<MetadataAsValue>(AssignCI->getOperand(1))->getMetadata())
1034*0fca6ea1SDimitry Andric           ->getType();
1035*0fca6ea1SDimitry Andric   if (CurrentType == AssignedType)
1036*0fca6ea1SDimitry Andric     return;
1037*0fca6ea1SDimitry Andric 
1038*0fca6ea1SDimitry Andric   // Builtin types cannot be redeclared or casted.
1039*0fca6ea1SDimitry Andric   if (CurrentType->isTargetExtTy())
1040*0fca6ea1SDimitry Andric     report_fatal_error("Type mismatch " + CurrentType->getTargetExtName() +
1041*0fca6ea1SDimitry Andric                            "/" + AssignedType->getTargetExtName() +
1042*0fca6ea1SDimitry Andric                            " for value " + V->getName(),
1043*0fca6ea1SDimitry Andric                        false);
1044*0fca6ea1SDimitry Andric 
1045*0fca6ea1SDimitry Andric   // Our previous guess about the type seems to be wrong, let's update
1046*0fca6ea1SDimitry Andric   // inferred type according to a new, more precise type information.
1047*0fca6ea1SDimitry Andric   updateAssignType(AssignCI, V, PoisonValue::get(AssignedType));
1048*0fca6ea1SDimitry Andric }
1049*0fca6ea1SDimitry Andric 
1050*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
1051*0fca6ea1SDimitry Andric     Instruction *I, Value *Pointer, Type *ExpectedElementType,
1052*0fca6ea1SDimitry Andric     unsigned OperandToReplace, IRBuilder<> &B) {
10531db9f3b2SDimitry Andric   // If Pointer is the result of nop BitCastInst (ptr -> ptr), use the source
10541db9f3b2SDimitry Andric   // pointer instead. The BitCastInst should be later removed when visited.
10551db9f3b2SDimitry Andric   while (BitCastInst *BC = dyn_cast<BitCastInst>(Pointer))
10561db9f3b2SDimitry Andric     Pointer = BC->getOperand(0);
10571db9f3b2SDimitry Andric 
1058*0fca6ea1SDimitry Andric   // Do not emit spv_ptrcast if Pointer's element type is ExpectedElementType
1059*0fca6ea1SDimitry Andric   Type *PointerElemTy = deduceElementTypeHelper(Pointer, false);
1060*0fca6ea1SDimitry Andric   if (PointerElemTy == ExpectedElementType ||
1061*0fca6ea1SDimitry Andric       isEquivalentTypes(PointerElemTy, ExpectedElementType))
10621db9f3b2SDimitry Andric     return;
10631db9f3b2SDimitry Andric 
1064*0fca6ea1SDimitry Andric   setInsertPointSkippingPhis(B, I);
1065*0fca6ea1SDimitry Andric   MetadataAsValue *VMD = buildMD(PoisonValue::get(ExpectedElementType));
1066*0fca6ea1SDimitry Andric   unsigned AddressSpace = getPointerAddressSpace(Pointer->getType());
10671db9f3b2SDimitry Andric   bool FirstPtrCastOrAssignPtrType = true;
10681db9f3b2SDimitry Andric 
10691db9f3b2SDimitry Andric   // Do not emit new spv_ptrcast if equivalent one already exists or when
10701db9f3b2SDimitry Andric   // spv_assign_ptr_type already targets this pointer with the same element
10711db9f3b2SDimitry Andric   // type.
10721db9f3b2SDimitry Andric   for (auto User : Pointer->users()) {
10731db9f3b2SDimitry Andric     auto *II = dyn_cast<IntrinsicInst>(User);
10741db9f3b2SDimitry Andric     if (!II ||
10751db9f3b2SDimitry Andric         (II->getIntrinsicID() != Intrinsic::spv_assign_ptr_type &&
10761db9f3b2SDimitry Andric          II->getIntrinsicID() != Intrinsic::spv_ptrcast) ||
10771db9f3b2SDimitry Andric         II->getOperand(0) != Pointer)
10781db9f3b2SDimitry Andric       continue;
10791db9f3b2SDimitry Andric 
10801db9f3b2SDimitry Andric     // There is some spv_ptrcast/spv_assign_ptr_type already targeting this
10811db9f3b2SDimitry Andric     // pointer.
10821db9f3b2SDimitry Andric     FirstPtrCastOrAssignPtrType = false;
10831db9f3b2SDimitry Andric     if (II->getOperand(1) != VMD ||
10841db9f3b2SDimitry Andric         dyn_cast<ConstantInt>(II->getOperand(2))->getSExtValue() !=
10851db9f3b2SDimitry Andric             AddressSpace)
10861db9f3b2SDimitry Andric       continue;
10871db9f3b2SDimitry Andric 
10881db9f3b2SDimitry Andric     // The spv_ptrcast/spv_assign_ptr_type targeting this pointer is of the same
10891db9f3b2SDimitry Andric     // element type and address space.
10901db9f3b2SDimitry Andric     if (II->getIntrinsicID() != Intrinsic::spv_ptrcast)
10911db9f3b2SDimitry Andric       return;
10921db9f3b2SDimitry Andric 
10931db9f3b2SDimitry Andric     // This must be a spv_ptrcast, do not emit new if this one has the same BB
10941db9f3b2SDimitry Andric     // as I. Otherwise, search for other spv_ptrcast/spv_assign_ptr_type.
10951db9f3b2SDimitry Andric     if (II->getParent() != I->getParent())
10961db9f3b2SDimitry Andric       continue;
10971db9f3b2SDimitry Andric 
10981db9f3b2SDimitry Andric     I->setOperand(OperandToReplace, II);
10991db9f3b2SDimitry Andric     return;
11001db9f3b2SDimitry Andric   }
11011db9f3b2SDimitry Andric 
1102*0fca6ea1SDimitry Andric   // // Do not emit spv_ptrcast if it would cast to the default pointer element
1103*0fca6ea1SDimitry Andric   // // type (i8) of the same address space.
1104*0fca6ea1SDimitry Andric   // if (ExpectedElementType->isIntegerTy(8))
1105*0fca6ea1SDimitry Andric   //   return;
1106*0fca6ea1SDimitry Andric 
1107*0fca6ea1SDimitry Andric   // If this would be the first spv_ptrcast, do not emit spv_ptrcast and emit
1108*0fca6ea1SDimitry Andric   // spv_assign_ptr_type instead.
1109*0fca6ea1SDimitry Andric   if (FirstPtrCastOrAssignPtrType &&
1110*0fca6ea1SDimitry Andric       (isa<Instruction>(Pointer) || isa<Argument>(Pointer))) {
1111*0fca6ea1SDimitry Andric     buildAssignPtr(B, ExpectedElementType, Pointer);
1112*0fca6ea1SDimitry Andric     return;
1113*0fca6ea1SDimitry Andric   }
1114*0fca6ea1SDimitry Andric 
1115*0fca6ea1SDimitry Andric   // Emit spv_ptrcast
1116*0fca6ea1SDimitry Andric   SmallVector<Type *, 2> Types = {Pointer->getType(), Pointer->getType()};
1117*0fca6ea1SDimitry Andric   SmallVector<Value *, 2> Args = {Pointer, VMD, B.getInt32(AddressSpace)};
1118*0fca6ea1SDimitry Andric   auto *PtrCastI = B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
1119*0fca6ea1SDimitry Andric   I->setOperand(OperandToReplace, PtrCastI);
1120*0fca6ea1SDimitry Andric }
1121*0fca6ea1SDimitry Andric 
1122*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
1123*0fca6ea1SDimitry Andric                                                          IRBuilder<> &B) {
1124*0fca6ea1SDimitry Andric   // Handle basic instructions:
1125*0fca6ea1SDimitry Andric   StoreInst *SI = dyn_cast<StoreInst>(I);
1126*0fca6ea1SDimitry Andric   if (IsKernelArgInt8(F, SI)) {
1127*0fca6ea1SDimitry Andric     return replacePointerOperandWithPtrCast(
1128*0fca6ea1SDimitry Andric         I, SI->getValueOperand(), IntegerType::getInt8Ty(F->getContext()), 0,
1129*0fca6ea1SDimitry Andric         B);
1130*0fca6ea1SDimitry Andric   } else if (SI) {
1131*0fca6ea1SDimitry Andric     Value *Op = SI->getValueOperand();
1132*0fca6ea1SDimitry Andric     Type *OpTy = Op->getType();
1133*0fca6ea1SDimitry Andric     if (auto *OpI = dyn_cast<Instruction>(Op))
1134*0fca6ea1SDimitry Andric       OpTy = restoreMutatedType(GR, OpI, OpTy);
1135*0fca6ea1SDimitry Andric     if (OpTy == Op->getType())
1136*0fca6ea1SDimitry Andric       OpTy = deduceElementTypeByValueDeep(OpTy, Op, false);
1137*0fca6ea1SDimitry Andric     return replacePointerOperandWithPtrCast(I, SI->getPointerOperand(), OpTy, 1,
1138*0fca6ea1SDimitry Andric                                             B);
1139*0fca6ea1SDimitry Andric   } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
1140*0fca6ea1SDimitry Andric     return replacePointerOperandWithPtrCast(I, LI->getPointerOperand(),
1141*0fca6ea1SDimitry Andric                                             LI->getType(), 0, B);
1142*0fca6ea1SDimitry Andric   } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
1143*0fca6ea1SDimitry Andric     return replacePointerOperandWithPtrCast(I, GEPI->getPointerOperand(),
1144*0fca6ea1SDimitry Andric                                             GEPI->getSourceElementType(), 0, B);
1145*0fca6ea1SDimitry Andric   }
1146*0fca6ea1SDimitry Andric 
1147*0fca6ea1SDimitry Andric   // Handle calls to builtins (non-intrinsics):
1148*0fca6ea1SDimitry Andric   CallInst *CI = dyn_cast<CallInst>(I);
1149*0fca6ea1SDimitry Andric   if (!CI || CI->isIndirectCall() || CI->isInlineAsm() ||
1150*0fca6ea1SDimitry Andric       !CI->getCalledFunction() || CI->getCalledFunction()->isIntrinsic())
11511db9f3b2SDimitry Andric     return;
11521db9f3b2SDimitry Andric 
1153*0fca6ea1SDimitry Andric   // collect information about formal parameter types
1154*0fca6ea1SDimitry Andric   std::string DemangledName =
1155*0fca6ea1SDimitry Andric       getOclOrSpirvBuiltinDemangledName(CI->getCalledFunction()->getName());
1156*0fca6ea1SDimitry Andric   Function *CalledF = CI->getCalledFunction();
1157*0fca6ea1SDimitry Andric   SmallVector<Type *, 4> CalledArgTys;
1158*0fca6ea1SDimitry Andric   bool HaveTypes = false;
1159*0fca6ea1SDimitry Andric   for (unsigned OpIdx = 0; OpIdx < CalledF->arg_size(); ++OpIdx) {
1160*0fca6ea1SDimitry Andric     Argument *CalledArg = CalledF->getArg(OpIdx);
1161*0fca6ea1SDimitry Andric     Type *ArgType = CalledArg->getType();
1162*0fca6ea1SDimitry Andric     if (!isPointerTy(ArgType)) {
1163*0fca6ea1SDimitry Andric       CalledArgTys.push_back(nullptr);
1164*0fca6ea1SDimitry Andric     } else if (isTypedPointerTy(ArgType)) {
1165*0fca6ea1SDimitry Andric       CalledArgTys.push_back(cast<TypedPointerType>(ArgType)->getElementType());
1166*0fca6ea1SDimitry Andric       HaveTypes = true;
11671db9f3b2SDimitry Andric     } else {
1168*0fca6ea1SDimitry Andric       Type *ElemTy = GR->findDeducedElementType(CalledArg);
1169*0fca6ea1SDimitry Andric       if (!ElemTy && hasPointeeTypeAttr(CalledArg))
1170*0fca6ea1SDimitry Andric         ElemTy = getPointeeTypeByAttr(CalledArg);
1171*0fca6ea1SDimitry Andric       if (!ElemTy) {
1172*0fca6ea1SDimitry Andric         ElemTy = getPointeeTypeByCallInst(DemangledName, CalledF, OpIdx);
1173*0fca6ea1SDimitry Andric         if (ElemTy) {
1174*0fca6ea1SDimitry Andric           GR->addDeducedElementType(CalledArg, ElemTy);
1175*0fca6ea1SDimitry Andric         } else {
1176*0fca6ea1SDimitry Andric           for (User *U : CalledArg->users()) {
1177*0fca6ea1SDimitry Andric             if (Instruction *Inst = dyn_cast<Instruction>(U)) {
1178*0fca6ea1SDimitry Andric               if ((ElemTy = deduceElementTypeHelper(Inst, false)) != nullptr)
1179*0fca6ea1SDimitry Andric                 break;
1180*0fca6ea1SDimitry Andric             }
1181*0fca6ea1SDimitry Andric           }
1182*0fca6ea1SDimitry Andric         }
1183*0fca6ea1SDimitry Andric       }
1184*0fca6ea1SDimitry Andric       HaveTypes |= ElemTy != nullptr;
1185*0fca6ea1SDimitry Andric       CalledArgTys.push_back(ElemTy);
1186*0fca6ea1SDimitry Andric     }
1187*0fca6ea1SDimitry Andric   }
1188*0fca6ea1SDimitry Andric 
1189*0fca6ea1SDimitry Andric   if (DemangledName.empty() && !HaveTypes)
11901db9f3b2SDimitry Andric     return;
1191*0fca6ea1SDimitry Andric 
1192*0fca6ea1SDimitry Andric   for (unsigned OpIdx = 0; OpIdx < CI->arg_size(); OpIdx++) {
1193*0fca6ea1SDimitry Andric     Value *ArgOperand = CI->getArgOperand(OpIdx);
1194*0fca6ea1SDimitry Andric     if (!isPointerTy(ArgOperand->getType()))
1195*0fca6ea1SDimitry Andric       continue;
1196*0fca6ea1SDimitry Andric 
1197*0fca6ea1SDimitry Andric     // Constants (nulls/undefs) are handled in insertAssignPtrTypeIntrs()
1198*0fca6ea1SDimitry Andric     if (!isa<Instruction>(ArgOperand) && !isa<Argument>(ArgOperand)) {
1199*0fca6ea1SDimitry Andric       // However, we may have assumptions about the formal argument's type and
1200*0fca6ea1SDimitry Andric       // may have a need to insert a ptr cast for the actual parameter of this
1201*0fca6ea1SDimitry Andric       // call.
1202*0fca6ea1SDimitry Andric       Argument *CalledArg = CalledF->getArg(OpIdx);
1203*0fca6ea1SDimitry Andric       if (!GR->findDeducedElementType(CalledArg))
1204*0fca6ea1SDimitry Andric         continue;
1205*0fca6ea1SDimitry Andric     }
1206*0fca6ea1SDimitry Andric 
1207*0fca6ea1SDimitry Andric     Type *ExpectedType =
1208*0fca6ea1SDimitry Andric         OpIdx < CalledArgTys.size() ? CalledArgTys[OpIdx] : nullptr;
1209*0fca6ea1SDimitry Andric     if (!ExpectedType && !DemangledName.empty())
1210*0fca6ea1SDimitry Andric       ExpectedType = SPIRV::parseBuiltinCallArgumentBaseType(
1211*0fca6ea1SDimitry Andric           DemangledName, OpIdx, I->getContext());
1212*0fca6ea1SDimitry Andric     if (!ExpectedType || ExpectedType->isVoidTy())
1213*0fca6ea1SDimitry Andric       continue;
1214*0fca6ea1SDimitry Andric 
1215*0fca6ea1SDimitry Andric     if (ExpectedType->isTargetExtTy())
1216*0fca6ea1SDimitry Andric       insertAssignPtrTypeTargetExt(cast<TargetExtType>(ExpectedType),
1217*0fca6ea1SDimitry Andric                                    ArgOperand, B);
1218*0fca6ea1SDimitry Andric     else
1219*0fca6ea1SDimitry Andric       replacePointerOperandWithPtrCast(CI, ArgOperand, ExpectedType, OpIdx, B);
12201db9f3b2SDimitry Andric   }
12211db9f3b2SDimitry Andric }
12221db9f3b2SDimitry Andric 
122381ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
122481ad6265SDimitry Andric   SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(),
122581ad6265SDimitry Andric                                   I.getOperand(1)->getType(),
122681ad6265SDimitry Andric                                   I.getOperand(2)->getType()};
1227*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1228*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
122981ad6265SDimitry Andric   SmallVector<Value *> Args(I.op_begin(), I.op_end());
1230*0fca6ea1SDimitry Andric   auto *NewI = B.CreateIntrinsic(Intrinsic::spv_insertelt, {Types}, {Args});
123181ad6265SDimitry Andric   std::string InstName = I.hasName() ? I.getName().str() : "";
123281ad6265SDimitry Andric   I.replaceAllUsesWith(NewI);
123381ad6265SDimitry Andric   I.eraseFromParent();
123481ad6265SDimitry Andric   NewI->setName(InstName);
123581ad6265SDimitry Andric   return NewI;
123681ad6265SDimitry Andric }
123781ad6265SDimitry Andric 
123881ad6265SDimitry Andric Instruction *
123981ad6265SDimitry Andric SPIRVEmitIntrinsics::visitExtractElementInst(ExtractElementInst &I) {
1240*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1241*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
124281ad6265SDimitry Andric   SmallVector<Type *, 3> Types = {I.getType(), I.getVectorOperandType(),
124381ad6265SDimitry Andric                                   I.getIndexOperand()->getType()};
124481ad6265SDimitry Andric   SmallVector<Value *, 2> Args = {I.getVectorOperand(), I.getIndexOperand()};
1245*0fca6ea1SDimitry Andric   auto *NewI = B.CreateIntrinsic(Intrinsic::spv_extractelt, {Types}, {Args});
124681ad6265SDimitry Andric   std::string InstName = I.hasName() ? I.getName().str() : "";
124781ad6265SDimitry Andric   I.replaceAllUsesWith(NewI);
124881ad6265SDimitry Andric   I.eraseFromParent();
124981ad6265SDimitry Andric   NewI->setName(InstName);
125081ad6265SDimitry Andric   return NewI;
125181ad6265SDimitry Andric }
125281ad6265SDimitry Andric 
125381ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) {
1254*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1255*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
125681ad6265SDimitry Andric   SmallVector<Type *, 1> Types = {I.getInsertedValueOperand()->getType()};
125781ad6265SDimitry Andric   SmallVector<Value *> Args;
125881ad6265SDimitry Andric   for (auto &Op : I.operands())
125981ad6265SDimitry Andric     if (isa<UndefValue>(Op))
1260*0fca6ea1SDimitry Andric       Args.push_back(UndefValue::get(B.getInt32Ty()));
126181ad6265SDimitry Andric     else
126281ad6265SDimitry Andric       Args.push_back(Op);
126381ad6265SDimitry Andric   for (auto &Op : I.indices())
1264*0fca6ea1SDimitry Andric     Args.push_back(B.getInt32(Op));
126581ad6265SDimitry Andric   Instruction *NewI =
1266*0fca6ea1SDimitry Andric       B.CreateIntrinsic(Intrinsic::spv_insertv, {Types}, {Args});
1267*0fca6ea1SDimitry Andric   replaceMemInstrUses(&I, NewI, B);
126881ad6265SDimitry Andric   return NewI;
126981ad6265SDimitry Andric }
127081ad6265SDimitry Andric 
127181ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
1272*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1273*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
127481ad6265SDimitry Andric   SmallVector<Value *> Args;
127581ad6265SDimitry Andric   for (auto &Op : I.operands())
127681ad6265SDimitry Andric     Args.push_back(Op);
127781ad6265SDimitry Andric   for (auto &Op : I.indices())
1278*0fca6ea1SDimitry Andric     Args.push_back(B.getInt32(Op));
127981ad6265SDimitry Andric   auto *NewI =
1280*0fca6ea1SDimitry Andric       B.CreateIntrinsic(Intrinsic::spv_extractv, {I.getType()}, {Args});
128181ad6265SDimitry Andric   I.replaceAllUsesWith(NewI);
128281ad6265SDimitry Andric   I.eraseFromParent();
128381ad6265SDimitry Andric   return NewI;
128481ad6265SDimitry Andric }
128581ad6265SDimitry Andric 
128681ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitLoadInst(LoadInst &I) {
128781ad6265SDimitry Andric   if (!I.getType()->isAggregateType())
128881ad6265SDimitry Andric     return &I;
1289*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1290*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
129181ad6265SDimitry Andric   TrackConstants = false;
129281ad6265SDimitry Andric   const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
129381ad6265SDimitry Andric   MachineMemOperand::Flags Flags =
1294*0fca6ea1SDimitry Andric       TLI->getLoadMemOperandFlags(I, F->getDataLayout());
129581ad6265SDimitry Andric   auto *NewI =
1296*0fca6ea1SDimitry Andric       B.CreateIntrinsic(Intrinsic::spv_load, {I.getOperand(0)->getType()},
1297*0fca6ea1SDimitry Andric                         {I.getPointerOperand(), B.getInt16(Flags),
1298*0fca6ea1SDimitry Andric                          B.getInt8(I.getAlign().value())});
1299*0fca6ea1SDimitry Andric   replaceMemInstrUses(&I, NewI, B);
130081ad6265SDimitry Andric   return NewI;
130181ad6265SDimitry Andric }
130281ad6265SDimitry Andric 
130381ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) {
130481ad6265SDimitry Andric   if (!AggrStores.contains(&I))
130581ad6265SDimitry Andric     return &I;
1306*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1307*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
130881ad6265SDimitry Andric   TrackConstants = false;
130981ad6265SDimitry Andric   const auto *TLI = TM->getSubtargetImpl()->getTargetLowering();
131081ad6265SDimitry Andric   MachineMemOperand::Flags Flags =
1311*0fca6ea1SDimitry Andric       TLI->getStoreMemOperandFlags(I, F->getDataLayout());
131281ad6265SDimitry Andric   auto *PtrOp = I.getPointerOperand();
1313*0fca6ea1SDimitry Andric   auto *NewI = B.CreateIntrinsic(
1314fcaf7f86SDimitry Andric       Intrinsic::spv_store, {I.getValueOperand()->getType(), PtrOp->getType()},
1315*0fca6ea1SDimitry Andric       {I.getValueOperand(), PtrOp, B.getInt16(Flags),
1316*0fca6ea1SDimitry Andric        B.getInt8(I.getAlign().value())});
131781ad6265SDimitry Andric   I.eraseFromParent();
131881ad6265SDimitry Andric   return NewI;
131981ad6265SDimitry Andric }
132081ad6265SDimitry Andric 
132181ad6265SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitAllocaInst(AllocaInst &I) {
1322*0fca6ea1SDimitry Andric   Value *ArraySize = nullptr;
1323*0fca6ea1SDimitry Andric   if (I.isArrayAllocation()) {
1324*0fca6ea1SDimitry Andric     const SPIRVSubtarget *STI = TM->getSubtargetImpl(*I.getFunction());
1325*0fca6ea1SDimitry Andric     if (!STI->canUseExtension(
1326*0fca6ea1SDimitry Andric             SPIRV::Extension::SPV_INTEL_variable_length_array))
1327*0fca6ea1SDimitry Andric       report_fatal_error(
1328*0fca6ea1SDimitry Andric           "array allocation: this instruction requires the following "
1329*0fca6ea1SDimitry Andric           "SPIR-V extension: SPV_INTEL_variable_length_array",
1330*0fca6ea1SDimitry Andric           false);
1331*0fca6ea1SDimitry Andric     ArraySize = I.getArraySize();
1332*0fca6ea1SDimitry Andric   }
1333*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1334*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
133581ad6265SDimitry Andric   TrackConstants = false;
1336bdd1243dSDimitry Andric   Type *PtrTy = I.getType();
1337*0fca6ea1SDimitry Andric   auto *NewI =
1338*0fca6ea1SDimitry Andric       ArraySize ? B.CreateIntrinsic(Intrinsic::spv_alloca_array,
1339*0fca6ea1SDimitry Andric                                     {PtrTy, ArraySize->getType()}, {ArraySize})
1340*0fca6ea1SDimitry Andric                 : B.CreateIntrinsic(Intrinsic::spv_alloca, {PtrTy}, {});
1341bdd1243dSDimitry Andric   std::string InstName = I.hasName() ? I.getName().str() : "";
1342bdd1243dSDimitry Andric   I.replaceAllUsesWith(NewI);
1343bdd1243dSDimitry Andric   I.eraseFromParent();
1344bdd1243dSDimitry Andric   NewI->setName(InstName);
1345bdd1243dSDimitry Andric   return NewI;
134681ad6265SDimitry Andric }
134781ad6265SDimitry Andric 
1348fcaf7f86SDimitry Andric Instruction *SPIRVEmitIntrinsics::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
1349fcaf7f86SDimitry Andric   assert(I.getType()->isAggregateType() && "Aggregate result is expected");
1350*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1351*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
1352fcaf7f86SDimitry Andric   SmallVector<Value *> Args;
1353fcaf7f86SDimitry Andric   for (auto &Op : I.operands())
1354fcaf7f86SDimitry Andric     Args.push_back(Op);
1355*0fca6ea1SDimitry Andric   Args.push_back(B.getInt32(I.getSyncScopeID()));
1356*0fca6ea1SDimitry Andric   Args.push_back(B.getInt32(
1357fcaf7f86SDimitry Andric       static_cast<uint32_t>(getMemSemantics(I.getSuccessOrdering()))));
1358*0fca6ea1SDimitry Andric   Args.push_back(B.getInt32(
1359fcaf7f86SDimitry Andric       static_cast<uint32_t>(getMemSemantics(I.getFailureOrdering()))));
1360*0fca6ea1SDimitry Andric   auto *NewI = B.CreateIntrinsic(Intrinsic::spv_cmpxchg,
1361fcaf7f86SDimitry Andric                                  {I.getPointerOperand()->getType()}, {Args});
1362*0fca6ea1SDimitry Andric   replaceMemInstrUses(&I, NewI, B);
1363fcaf7f86SDimitry Andric   return NewI;
1364fcaf7f86SDimitry Andric }
1365fcaf7f86SDimitry Andric 
1366bdd1243dSDimitry Andric Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
1367*0fca6ea1SDimitry Andric   IRBuilder<> B(I.getParent());
1368*0fca6ea1SDimitry Andric   B.SetInsertPoint(&I);
1369*0fca6ea1SDimitry Andric   B.CreateIntrinsic(Intrinsic::spv_unreachable, {}, {});
1370bdd1243dSDimitry Andric   return &I;
1371bdd1243dSDimitry Andric }
1372bdd1243dSDimitry Andric 
1373*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
1374*0fca6ea1SDimitry Andric                                              IRBuilder<> &B) {
137581ad6265SDimitry Andric   // Skip special artifical variable llvm.global.annotations.
137681ad6265SDimitry Andric   if (GV.getName() == "llvm.global.annotations")
137781ad6265SDimitry Andric     return;
137881ad6265SDimitry Andric   if (GV.hasInitializer() && !isa<UndefValue>(GV.getInitializer())) {
1379*0fca6ea1SDimitry Andric     // Deduce element type and store results in Global Registry.
1380*0fca6ea1SDimitry Andric     // Result is ignored, because TypedPointerType is not supported
1381*0fca6ea1SDimitry Andric     // by llvm IR general logic.
1382*0fca6ea1SDimitry Andric     deduceElementTypeHelper(&GV, false);
138381ad6265SDimitry Andric     Constant *Init = GV.getInitializer();
1384*0fca6ea1SDimitry Andric     Type *Ty = isAggrConstForceInt32(Init) ? B.getInt32Ty() : Init->getType();
1385*0fca6ea1SDimitry Andric     Constant *Const = isAggrConstForceInt32(Init) ? B.getInt32(1) : Init;
1386*0fca6ea1SDimitry Andric     auto *InitInst = B.CreateIntrinsic(Intrinsic::spv_init_global,
138781ad6265SDimitry Andric                                        {GV.getType(), Ty}, {&GV, Const});
138881ad6265SDimitry Andric     InitInst->setArgOperand(1, Init);
138981ad6265SDimitry Andric   }
139081ad6265SDimitry Andric   if ((!GV.hasInitializer() || isa<UndefValue>(GV.getInitializer())) &&
139181ad6265SDimitry Andric       GV.getNumUses() == 0)
1392*0fca6ea1SDimitry Andric     B.CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV);
139381ad6265SDimitry Andric }
139481ad6265SDimitry Andric 
1395*0fca6ea1SDimitry Andric // Return true, if we can't decide what is the pointee type now and will get
1396*0fca6ea1SDimitry Andric // back to the question later. Return false is spv_assign_ptr_type is not needed
1397*0fca6ea1SDimitry Andric // or can be inserted immediately.
1398*0fca6ea1SDimitry Andric bool SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I,
1399*0fca6ea1SDimitry Andric                                                    IRBuilder<> &B,
1400*0fca6ea1SDimitry Andric                                                    bool UnknownElemTypeI8) {
1401*0fca6ea1SDimitry Andric   reportFatalOnTokenType(I);
1402*0fca6ea1SDimitry Andric   if (!isPointerTy(I->getType()) || !requireAssignType(I) ||
1403*0fca6ea1SDimitry Andric       isa<BitCastInst>(I))
1404*0fca6ea1SDimitry Andric     return false;
14055f757f3fSDimitry Andric 
1406*0fca6ea1SDimitry Andric   setInsertPointAfterDef(B, I);
1407*0fca6ea1SDimitry Andric   if (Type *ElemTy = deduceElementType(I, UnknownElemTypeI8)) {
1408*0fca6ea1SDimitry Andric     buildAssignPtr(B, ElemTy, I);
1409*0fca6ea1SDimitry Andric     return false;
1410*0fca6ea1SDimitry Andric   }
1411*0fca6ea1SDimitry Andric   return true;
14125f757f3fSDimitry Andric }
14135f757f3fSDimitry Andric 
1414*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
1415*0fca6ea1SDimitry Andric                                                 IRBuilder<> &B) {
1416*0fca6ea1SDimitry Andric   // TODO: extend the list of functions with known result types
1417*0fca6ea1SDimitry Andric   static StringMap<unsigned> ResTypeWellKnown = {
1418*0fca6ea1SDimitry Andric       {"async_work_group_copy", WellKnownTypes::Event},
1419*0fca6ea1SDimitry Andric       {"async_work_group_strided_copy", WellKnownTypes::Event},
1420*0fca6ea1SDimitry Andric       {"__spirv_GroupAsyncCopy", WellKnownTypes::Event}};
1421*0fca6ea1SDimitry Andric 
1422*0fca6ea1SDimitry Andric   reportFatalOnTokenType(I);
1423*0fca6ea1SDimitry Andric 
1424*0fca6ea1SDimitry Andric   bool IsKnown = false;
1425*0fca6ea1SDimitry Andric   if (auto *CI = dyn_cast<CallInst>(I)) {
1426*0fca6ea1SDimitry Andric     if (!CI->isIndirectCall() && !CI->isInlineAsm() &&
1427*0fca6ea1SDimitry Andric         CI->getCalledFunction() && !CI->getCalledFunction()->isIntrinsic()) {
1428*0fca6ea1SDimitry Andric       Function *CalledF = CI->getCalledFunction();
1429*0fca6ea1SDimitry Andric       std::string DemangledName =
1430*0fca6ea1SDimitry Andric           getOclOrSpirvBuiltinDemangledName(CalledF->getName());
1431*0fca6ea1SDimitry Andric       if (DemangledName.length() > 0)
1432*0fca6ea1SDimitry Andric         DemangledName = SPIRV::lookupBuiltinNameHelper(DemangledName);
1433*0fca6ea1SDimitry Andric       auto ResIt = ResTypeWellKnown.find(DemangledName);
1434*0fca6ea1SDimitry Andric       if (ResIt != ResTypeWellKnown.end()) {
1435*0fca6ea1SDimitry Andric         IsKnown = true;
1436*0fca6ea1SDimitry Andric         setInsertPointAfterDef(B, I);
1437*0fca6ea1SDimitry Andric         switch (ResIt->second) {
1438*0fca6ea1SDimitry Andric         case WellKnownTypes::Event:
1439*0fca6ea1SDimitry Andric           buildAssignType(B, TargetExtType::get(I->getContext(), "spirv.Event"),
1440*0fca6ea1SDimitry Andric                           I);
1441*0fca6ea1SDimitry Andric           break;
1442*0fca6ea1SDimitry Andric         }
1443*0fca6ea1SDimitry Andric       }
1444*0fca6ea1SDimitry Andric     }
14455f757f3fSDimitry Andric   }
14465f757f3fSDimitry Andric 
144781ad6265SDimitry Andric   Type *Ty = I->getType();
1448*0fca6ea1SDimitry Andric   if (!IsKnown && !Ty->isVoidTy() && !isPointerTy(Ty) && requireAssignType(I)) {
1449*0fca6ea1SDimitry Andric     setInsertPointAfterDef(B, I);
145081ad6265SDimitry Andric     Type *TypeToAssign = Ty;
145181ad6265SDimitry Andric     if (auto *II = dyn_cast<IntrinsicInst>(I)) {
145206c3fb27SDimitry Andric       if (II->getIntrinsicID() == Intrinsic::spv_const_composite ||
145306c3fb27SDimitry Andric           II->getIntrinsicID() == Intrinsic::spv_undef) {
1454*0fca6ea1SDimitry Andric         auto It = AggrConstTypes.find(II);
1455*0fca6ea1SDimitry Andric         if (It == AggrConstTypes.end())
1456*0fca6ea1SDimitry Andric           report_fatal_error("Unknown composite intrinsic type");
1457*0fca6ea1SDimitry Andric         TypeToAssign = It->second;
145881ad6265SDimitry Andric       }
145981ad6265SDimitry Andric     }
1460*0fca6ea1SDimitry Andric     TypeToAssign = restoreMutatedType(GR, I, TypeToAssign);
1461*0fca6ea1SDimitry Andric     buildAssignType(B, TypeToAssign, I);
146281ad6265SDimitry Andric   }
146381ad6265SDimitry Andric   for (const auto &Op : I->operands()) {
146481ad6265SDimitry Andric     if (isa<ConstantPointerNull>(Op) || isa<UndefValue>(Op) ||
146581ad6265SDimitry Andric         // Check GetElementPtrConstantExpr case.
146681ad6265SDimitry Andric         (isa<ConstantExpr>(Op) && isa<GEPOperator>(Op))) {
1467*0fca6ea1SDimitry Andric       setInsertPointSkippingPhis(B, I);
1468*0fca6ea1SDimitry Andric       Type *OpTy = Op->getType();
1469*0fca6ea1SDimitry Andric       if (isa<UndefValue>(Op) && OpTy->isAggregateType()) {
1470*0fca6ea1SDimitry Andric         CallInst *AssignCI =
1471*0fca6ea1SDimitry Andric             buildIntrWithMD(Intrinsic::spv_assign_type, {B.getInt32Ty()}, Op,
1472*0fca6ea1SDimitry Andric                             UndefValue::get(B.getInt32Ty()), {}, B);
1473*0fca6ea1SDimitry Andric         GR->addAssignPtrTypeInstr(Op, AssignCI);
1474*0fca6ea1SDimitry Andric       } else if (!isa<Instruction>(Op)) {
1475*0fca6ea1SDimitry Andric         Type *OpTy = Op->getType();
1476*0fca6ea1SDimitry Andric         if (auto PType = dyn_cast<TypedPointerType>(OpTy)) {
1477*0fca6ea1SDimitry Andric           buildAssignPtr(B, PType->getElementType(), Op);
1478*0fca6ea1SDimitry Andric         } else if (isPointerTy(OpTy)) {
1479*0fca6ea1SDimitry Andric           Type *ElemTy = GR->findDeducedElementType(Op);
1480*0fca6ea1SDimitry Andric           buildAssignPtr(B, ElemTy ? ElemTy : deduceElementType(Op, true), Op);
1481*0fca6ea1SDimitry Andric         } else {
1482*0fca6ea1SDimitry Andric           CallInst *AssignCI = buildIntrWithMD(Intrinsic::spv_assign_type,
1483*0fca6ea1SDimitry Andric                                                {OpTy}, Op, Op, {}, B);
1484*0fca6ea1SDimitry Andric           GR->addAssignPtrTypeInstr(Op, AssignCI);
1485*0fca6ea1SDimitry Andric         }
1486*0fca6ea1SDimitry Andric       }
148781ad6265SDimitry Andric     }
148881ad6265SDimitry Andric   }
148981ad6265SDimitry Andric }
149081ad6265SDimitry Andric 
1491*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
1492*0fca6ea1SDimitry Andric                                                  IRBuilder<> &B) {
1493*0fca6ea1SDimitry Andric   if (MDNode *MD = I->getMetadata("spirv.Decorations")) {
1494*0fca6ea1SDimitry Andric     setInsertPointAfterDef(B, I);
1495*0fca6ea1SDimitry Andric     B.CreateIntrinsic(Intrinsic::spv_assign_decoration, {I->getType()},
1496*0fca6ea1SDimitry Andric                       {I, MetadataAsValue::get(I->getContext(), MD)});
1497*0fca6ea1SDimitry Andric   }
1498*0fca6ea1SDimitry Andric }
1499*0fca6ea1SDimitry Andric 
1500*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
1501*0fca6ea1SDimitry Andric                                                  IRBuilder<> &B) {
150281ad6265SDimitry Andric   auto *II = dyn_cast<IntrinsicInst>(I);
150381ad6265SDimitry Andric   if (II && II->getIntrinsicID() == Intrinsic::spv_const_composite &&
150481ad6265SDimitry Andric       TrackConstants) {
1505*0fca6ea1SDimitry Andric     setInsertPointAfterDef(B, I);
150681ad6265SDimitry Andric     auto t = AggrConsts.find(I);
150781ad6265SDimitry Andric     assert(t != AggrConsts.end());
1508*0fca6ea1SDimitry Andric     auto *NewOp =
1509*0fca6ea1SDimitry Andric         buildIntrWithMD(Intrinsic::spv_track_constant,
1510*0fca6ea1SDimitry Andric                         {II->getType(), II->getType()}, t->second, I, {}, B);
151181ad6265SDimitry Andric     I->replaceAllUsesWith(NewOp);
151281ad6265SDimitry Andric     NewOp->setArgOperand(0, I);
151381ad6265SDimitry Andric   }
1514*0fca6ea1SDimitry Andric   bool IsPhi = isa<PHINode>(I), BPrepared = false;
151581ad6265SDimitry Andric   for (const auto &Op : I->operands()) {
1516*0fca6ea1SDimitry Andric     if (isa<PHINode>(I) || isa<SwitchInst>(I))
151781ad6265SDimitry Andric       TrackConstants = false;
1518fcaf7f86SDimitry Andric     if ((isa<ConstantData>(Op) || isa<ConstantExpr>(Op)) && TrackConstants) {
151981ad6265SDimitry Andric       unsigned OpNo = Op.getOperandNo();
152081ad6265SDimitry Andric       if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
152181ad6265SDimitry Andric                  (II->paramHasAttr(OpNo, Attribute::ImmArg))))
152281ad6265SDimitry Andric         continue;
1523*0fca6ea1SDimitry Andric       if (!BPrepared) {
1524*0fca6ea1SDimitry Andric         IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
1525*0fca6ea1SDimitry Andric               : B.SetInsertPoint(I);
1526*0fca6ea1SDimitry Andric         BPrepared = true;
1527*0fca6ea1SDimitry Andric       }
1528*0fca6ea1SDimitry Andric       Value *OpTyVal = Op;
1529*0fca6ea1SDimitry Andric       if (Op->getType()->isTargetExtTy())
1530*0fca6ea1SDimitry Andric         OpTyVal = PoisonValue::get(Op->getType());
153181ad6265SDimitry Andric       auto *NewOp = buildIntrWithMD(Intrinsic::spv_track_constant,
1532*0fca6ea1SDimitry Andric                                     {Op->getType(), OpTyVal->getType()}, Op,
1533*0fca6ea1SDimitry Andric                                     OpTyVal, {}, B);
153481ad6265SDimitry Andric       I->setOperand(OpNo, NewOp);
153581ad6265SDimitry Andric     }
153681ad6265SDimitry Andric   }
153781ad6265SDimitry Andric   if (I->hasName()) {
1538*0fca6ea1SDimitry Andric     reportFatalOnTokenType(I);
1539*0fca6ea1SDimitry Andric     setInsertPointAfterDef(B, I);
154081ad6265SDimitry Andric     std::vector<Value *> Args = {I};
1541*0fca6ea1SDimitry Andric     addStringImm(I->getName(), B, Args);
1542*0fca6ea1SDimitry Andric     B.CreateIntrinsic(Intrinsic::spv_assign_name, {I->getType()}, Args);
1543*0fca6ea1SDimitry Andric   }
1544*0fca6ea1SDimitry Andric }
1545*0fca6ea1SDimitry Andric 
1546*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F,
1547*0fca6ea1SDimitry Andric                                                      unsigned OpIdx) {
1548*0fca6ea1SDimitry Andric   std::unordered_set<Function *> FVisited;
1549*0fca6ea1SDimitry Andric   return deduceFunParamElementType(F, OpIdx, FVisited);
1550*0fca6ea1SDimitry Andric }
1551*0fca6ea1SDimitry Andric 
1552*0fca6ea1SDimitry Andric Type *SPIRVEmitIntrinsics::deduceFunParamElementType(
1553*0fca6ea1SDimitry Andric     Function *F, unsigned OpIdx, std::unordered_set<Function *> &FVisited) {
1554*0fca6ea1SDimitry Andric   // maybe a cycle
1555*0fca6ea1SDimitry Andric   if (FVisited.find(F) != FVisited.end())
1556*0fca6ea1SDimitry Andric     return nullptr;
1557*0fca6ea1SDimitry Andric   FVisited.insert(F);
1558*0fca6ea1SDimitry Andric 
1559*0fca6ea1SDimitry Andric   std::unordered_set<Value *> Visited;
1560*0fca6ea1SDimitry Andric   SmallVector<std::pair<Function *, unsigned>> Lookup;
1561*0fca6ea1SDimitry Andric   // search in function's call sites
1562*0fca6ea1SDimitry Andric   for (User *U : F->users()) {
1563*0fca6ea1SDimitry Andric     CallInst *CI = dyn_cast<CallInst>(U);
1564*0fca6ea1SDimitry Andric     if (!CI || OpIdx >= CI->arg_size())
1565*0fca6ea1SDimitry Andric       continue;
1566*0fca6ea1SDimitry Andric     Value *OpArg = CI->getArgOperand(OpIdx);
1567*0fca6ea1SDimitry Andric     if (!isPointerTy(OpArg->getType()))
1568*0fca6ea1SDimitry Andric       continue;
1569*0fca6ea1SDimitry Andric     // maybe we already know operand's element type
1570*0fca6ea1SDimitry Andric     if (Type *KnownTy = GR->findDeducedElementType(OpArg))
1571*0fca6ea1SDimitry Andric       return KnownTy;
1572*0fca6ea1SDimitry Andric     // try to deduce from the operand itself
1573*0fca6ea1SDimitry Andric     Visited.clear();
1574*0fca6ea1SDimitry Andric     if (Type *Ty = deduceElementTypeHelper(OpArg, Visited, false))
1575*0fca6ea1SDimitry Andric       return Ty;
1576*0fca6ea1SDimitry Andric     // search in actual parameter's users
1577*0fca6ea1SDimitry Andric     for (User *OpU : OpArg->users()) {
1578*0fca6ea1SDimitry Andric       Instruction *Inst = dyn_cast<Instruction>(OpU);
1579*0fca6ea1SDimitry Andric       if (!Inst || Inst == CI)
1580*0fca6ea1SDimitry Andric         continue;
1581*0fca6ea1SDimitry Andric       Visited.clear();
1582*0fca6ea1SDimitry Andric       if (Type *Ty = deduceElementTypeHelper(Inst, Visited, false))
1583*0fca6ea1SDimitry Andric         return Ty;
1584*0fca6ea1SDimitry Andric     }
1585*0fca6ea1SDimitry Andric     // check if it's a formal parameter of the outer function
1586*0fca6ea1SDimitry Andric     if (!CI->getParent() || !CI->getParent()->getParent())
1587*0fca6ea1SDimitry Andric       continue;
1588*0fca6ea1SDimitry Andric     Function *OuterF = CI->getParent()->getParent();
1589*0fca6ea1SDimitry Andric     if (FVisited.find(OuterF) != FVisited.end())
1590*0fca6ea1SDimitry Andric       continue;
1591*0fca6ea1SDimitry Andric     for (unsigned i = 0; i < OuterF->arg_size(); ++i) {
1592*0fca6ea1SDimitry Andric       if (OuterF->getArg(i) == OpArg) {
1593*0fca6ea1SDimitry Andric         Lookup.push_back(std::make_pair(OuterF, i));
1594*0fca6ea1SDimitry Andric         break;
1595*0fca6ea1SDimitry Andric       }
1596*0fca6ea1SDimitry Andric     }
1597*0fca6ea1SDimitry Andric   }
1598*0fca6ea1SDimitry Andric 
1599*0fca6ea1SDimitry Andric   // search in function parameters
1600*0fca6ea1SDimitry Andric   for (auto &Pair : Lookup) {
1601*0fca6ea1SDimitry Andric     if (Type *Ty = deduceFunParamElementType(Pair.first, Pair.second, FVisited))
1602*0fca6ea1SDimitry Andric       return Ty;
1603*0fca6ea1SDimitry Andric   }
1604*0fca6ea1SDimitry Andric 
1605*0fca6ea1SDimitry Andric   return nullptr;
1606*0fca6ea1SDimitry Andric }
1607*0fca6ea1SDimitry Andric 
1608*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::processParamTypesByFunHeader(Function *F,
1609*0fca6ea1SDimitry Andric                                                        IRBuilder<> &B) {
1610*0fca6ea1SDimitry Andric   B.SetInsertPointPastAllocas(F);
1611*0fca6ea1SDimitry Andric   for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) {
1612*0fca6ea1SDimitry Andric     Argument *Arg = F->getArg(OpIdx);
1613*0fca6ea1SDimitry Andric     if (!isUntypedPointerTy(Arg->getType()))
1614*0fca6ea1SDimitry Andric       continue;
1615*0fca6ea1SDimitry Andric     Type *ElemTy = GR->findDeducedElementType(Arg);
1616*0fca6ea1SDimitry Andric     if (!ElemTy && hasPointeeTypeAttr(Arg) &&
1617*0fca6ea1SDimitry Andric         (ElemTy = getPointeeTypeByAttr(Arg)) != nullptr)
1618*0fca6ea1SDimitry Andric       buildAssignPtr(B, ElemTy, Arg);
1619*0fca6ea1SDimitry Andric   }
1620*0fca6ea1SDimitry Andric }
1621*0fca6ea1SDimitry Andric 
1622*0fca6ea1SDimitry Andric void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) {
1623*0fca6ea1SDimitry Andric   B.SetInsertPointPastAllocas(F);
1624*0fca6ea1SDimitry Andric   for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) {
1625*0fca6ea1SDimitry Andric     Argument *Arg = F->getArg(OpIdx);
1626*0fca6ea1SDimitry Andric     if (!isUntypedPointerTy(Arg->getType()))
1627*0fca6ea1SDimitry Andric       continue;
1628*0fca6ea1SDimitry Andric     Type *ElemTy = GR->findDeducedElementType(Arg);
1629*0fca6ea1SDimitry Andric     if (!ElemTy && (ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr)
1630*0fca6ea1SDimitry Andric       buildAssignPtr(B, ElemTy, Arg);
163181ad6265SDimitry Andric   }
163281ad6265SDimitry Andric }
163381ad6265SDimitry Andric 
163481ad6265SDimitry Andric bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
163581ad6265SDimitry Andric   if (Func.isDeclaration())
163681ad6265SDimitry Andric     return false;
1637*0fca6ea1SDimitry Andric 
1638*0fca6ea1SDimitry Andric   const SPIRVSubtarget &ST = TM->getSubtarget<SPIRVSubtarget>(Func);
1639*0fca6ea1SDimitry Andric   GR = ST.getSPIRVGlobalRegistry();
1640*0fca6ea1SDimitry Andric   InstrSet = ST.isOpenCLEnv() ? SPIRV::InstructionSet::OpenCL_std
1641*0fca6ea1SDimitry Andric                               : SPIRV::InstructionSet::GLSL_std_450;
1642*0fca6ea1SDimitry Andric 
164381ad6265SDimitry Andric   F = &Func;
1644*0fca6ea1SDimitry Andric   IRBuilder<> B(Func.getContext());
164581ad6265SDimitry Andric   AggrConsts.clear();
1646*0fca6ea1SDimitry Andric   AggrConstTypes.clear();
164781ad6265SDimitry Andric   AggrStores.clear();
164881ad6265SDimitry Andric 
1649*0fca6ea1SDimitry Andric   processParamTypesByFunHeader(F, B);
1650*0fca6ea1SDimitry Andric 
1651fcaf7f86SDimitry Andric   // StoreInst's operand type can be changed during the next transformations,
1652fcaf7f86SDimitry Andric   // so we need to store it in the set. Also store already transformed types.
1653fcaf7f86SDimitry Andric   for (auto &I : instructions(Func)) {
1654fcaf7f86SDimitry Andric     StoreInst *SI = dyn_cast<StoreInst>(&I);
1655fcaf7f86SDimitry Andric     if (!SI)
1656fcaf7f86SDimitry Andric       continue;
1657fcaf7f86SDimitry Andric     Type *ElTy = SI->getValueOperand()->getType();
16585f757f3fSDimitry Andric     if (ElTy->isAggregateType() || ElTy->isVectorTy())
1659fcaf7f86SDimitry Andric       AggrStores.insert(&I);
1660fcaf7f86SDimitry Andric   }
166181ad6265SDimitry Andric 
1662*0fca6ea1SDimitry Andric   B.SetInsertPoint(&Func.getEntryBlock(), Func.getEntryBlock().begin());
166381ad6265SDimitry Andric   for (auto &GV : Func.getParent()->globals())
1664*0fca6ea1SDimitry Andric     processGlobalValue(GV, B);
166581ad6265SDimitry Andric 
1666*0fca6ea1SDimitry Andric   preprocessUndefs(B);
1667*0fca6ea1SDimitry Andric   preprocessCompositeConstants(B);
166881ad6265SDimitry Andric   SmallVector<Instruction *> Worklist;
166981ad6265SDimitry Andric   for (auto &I : instructions(Func))
167081ad6265SDimitry Andric     Worklist.push_back(&I);
167181ad6265SDimitry Andric 
16725f757f3fSDimitry Andric   for (auto &I : Worklist) {
1673*0fca6ea1SDimitry Andric     // Don't emit intrinsincs for convergence intrinsics.
1674*0fca6ea1SDimitry Andric     if (isConvergenceIntrinsic(I))
1675*0fca6ea1SDimitry Andric       continue;
1676*0fca6ea1SDimitry Andric 
1677*0fca6ea1SDimitry Andric     bool Postpone = insertAssignPtrTypeIntrs(I, B, false);
1678*0fca6ea1SDimitry Andric     // if Postpone is true, we can't decide on pointee type yet
1679*0fca6ea1SDimitry Andric     insertAssignTypeIntrs(I, B);
1680*0fca6ea1SDimitry Andric     insertPtrCastOrAssignTypeInstr(I, B);
1681*0fca6ea1SDimitry Andric     insertSpirvDecorations(I, B);
1682*0fca6ea1SDimitry Andric     // if instruction requires a pointee type set, let's check if we know it
1683*0fca6ea1SDimitry Andric     // already, and force it to be i8 if not
1684*0fca6ea1SDimitry Andric     if (Postpone && !GR->findAssignPtrTypeInstr(I))
1685*0fca6ea1SDimitry Andric       insertAssignPtrTypeIntrs(I, B, true);
16865f757f3fSDimitry Andric   }
168781ad6265SDimitry Andric 
1688*0fca6ea1SDimitry Andric   for (auto &I : instructions(Func))
1689*0fca6ea1SDimitry Andric     deduceOperandElementType(&I);
1690*0fca6ea1SDimitry Andric 
169181ad6265SDimitry Andric   for (auto *I : Worklist) {
169281ad6265SDimitry Andric     TrackConstants = true;
169381ad6265SDimitry Andric     if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
1694*0fca6ea1SDimitry Andric       setInsertPointAfterDef(B, I);
16951db9f3b2SDimitry Andric     // Visitors return either the original/newly created instruction for further
16961db9f3b2SDimitry Andric     // processing, nullptr otherwise.
169781ad6265SDimitry Andric     I = visit(*I);
16981db9f3b2SDimitry Andric     if (!I)
16991db9f3b2SDimitry Andric       continue;
1700*0fca6ea1SDimitry Andric 
1701*0fca6ea1SDimitry Andric     // Don't emit intrinsics for convergence operations.
1702*0fca6ea1SDimitry Andric     if (isConvergenceIntrinsic(I))
1703*0fca6ea1SDimitry Andric       continue;
1704*0fca6ea1SDimitry Andric 
1705*0fca6ea1SDimitry Andric     processInstrAfterVisit(I, B);
170681ad6265SDimitry Andric   }
1707*0fca6ea1SDimitry Andric 
170881ad6265SDimitry Andric   return true;
170981ad6265SDimitry Andric }
171081ad6265SDimitry Andric 
1711*0fca6ea1SDimitry Andric // Try to deduce a better type for pointers to untyped ptr.
1712*0fca6ea1SDimitry Andric bool SPIRVEmitIntrinsics::postprocessTypes() {
1713*0fca6ea1SDimitry Andric   bool Changed = false;
1714*0fca6ea1SDimitry Andric   if (!GR)
1715*0fca6ea1SDimitry Andric     return Changed;
1716*0fca6ea1SDimitry Andric   for (auto IB = PostprocessWorklist.rbegin(), IE = PostprocessWorklist.rend();
1717*0fca6ea1SDimitry Andric        IB != IE; ++IB) {
1718*0fca6ea1SDimitry Andric     CallInst *AssignCI = GR->findAssignPtrTypeInstr(*IB);
1719*0fca6ea1SDimitry Andric     Type *KnownTy = GR->findDeducedElementType(*IB);
1720*0fca6ea1SDimitry Andric     if (!KnownTy || !AssignCI || !isa<Instruction>(AssignCI->getArgOperand(0)))
1721*0fca6ea1SDimitry Andric       continue;
1722*0fca6ea1SDimitry Andric     Instruction *I = cast<Instruction>(AssignCI->getArgOperand(0));
1723*0fca6ea1SDimitry Andric     for (User *U : I->users()) {
1724*0fca6ea1SDimitry Andric       Instruction *Inst = dyn_cast<Instruction>(U);
1725*0fca6ea1SDimitry Andric       if (!Inst || isa<IntrinsicInst>(Inst))
1726*0fca6ea1SDimitry Andric         continue;
1727*0fca6ea1SDimitry Andric       deduceOperandElementType(Inst, I, KnownTy, AssignCI);
1728*0fca6ea1SDimitry Andric       if (KnownTy != GR->findDeducedElementType(I)) {
1729*0fca6ea1SDimitry Andric         Changed = true;
1730*0fca6ea1SDimitry Andric         break;
1731*0fca6ea1SDimitry Andric       }
1732*0fca6ea1SDimitry Andric     }
1733*0fca6ea1SDimitry Andric   }
1734*0fca6ea1SDimitry Andric   return Changed;
1735*0fca6ea1SDimitry Andric }
1736*0fca6ea1SDimitry Andric 
1737*0fca6ea1SDimitry Andric bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
1738*0fca6ea1SDimitry Andric   bool Changed = false;
1739*0fca6ea1SDimitry Andric 
1740*0fca6ea1SDimitry Andric   UncompleteTypeInfo.clear();
1741*0fca6ea1SDimitry Andric   PostprocessWorklist.clear();
1742*0fca6ea1SDimitry Andric   for (auto &F : M)
1743*0fca6ea1SDimitry Andric     Changed |= runOnFunction(F);
1744*0fca6ea1SDimitry Andric 
1745*0fca6ea1SDimitry Andric   for (auto &F : M) {
1746*0fca6ea1SDimitry Andric     // check if function parameter types are set
1747*0fca6ea1SDimitry Andric     if (!F.isDeclaration() && !F.isIntrinsic()) {
1748*0fca6ea1SDimitry Andric       const SPIRVSubtarget &ST = TM->getSubtarget<SPIRVSubtarget>(F);
1749*0fca6ea1SDimitry Andric       GR = ST.getSPIRVGlobalRegistry();
1750*0fca6ea1SDimitry Andric       IRBuilder<> B(F.getContext());
1751*0fca6ea1SDimitry Andric       processParamTypes(&F, B);
1752*0fca6ea1SDimitry Andric     }
1753*0fca6ea1SDimitry Andric   }
1754*0fca6ea1SDimitry Andric 
1755*0fca6ea1SDimitry Andric   Changed |= postprocessTypes();
1756*0fca6ea1SDimitry Andric 
1757*0fca6ea1SDimitry Andric   return Changed;
1758*0fca6ea1SDimitry Andric }
1759*0fca6ea1SDimitry Andric 
1760*0fca6ea1SDimitry Andric ModulePass *llvm::createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM) {
176181ad6265SDimitry Andric   return new SPIRVEmitIntrinsics(TM);
176281ad6265SDimitry Andric }
1763