LLVM 23.0.0git
SPIRVEmitIntrinsics.cpp
Go to the documentation of this file.
1//===-- SPIRVEmitIntrinsics.cpp - emit SPIRV intrinsics ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The pass emits SPIRV intrinsics keeping essential high-level information for
10// the translation of LLVM IR to SPIR-V.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SPIRVEmitIntrinsics.h"
15#include "SPIRV.h"
16#include "SPIRVBuiltins.h"
17#include "SPIRVSubtarget.h"
18#include "SPIRVTargetMachine.h"
19#include "SPIRVUtils.h"
20#include "llvm/ADT/DenseMap.h"
21#include "llvm/ADT/DenseSet.h"
23#include "llvm/ADT/StringSet.h"
25#include "llvm/IR/Dominators.h"
26#include "llvm/IR/IRBuilder.h"
28#include "llvm/IR/InstVisitor.h"
29#include "llvm/IR/IntrinsicsSPIRV.h"
32#include "llvm/IR/Value.h"
34#include "llvm/Support/Debug.h"
36
37#include <cassert>
38#include <optional>
39#include <queue>
40
41// This pass performs the following transformation on LLVM IR level required
42// for the following translation to SPIR-V:
43// - replaces direct usages of aggregate constants with target-specific
44// intrinsics;
45// - replaces aggregates-related instructions (extract/insert, ld/st, etc)
46// with a target-specific intrinsics;
47// - emits intrinsics for the global variable initializers since IRTranslator
48// doesn't handle them and it's not very convenient to translate them
49// ourselves;
50// - emits intrinsics to keep track of the string names assigned to the values;
51// - emits intrinsics to keep track of constants (this is necessary to have an
52// LLVM IR constant after the IRTranslation is completed) for their further
53// deduplication;
54// - emits intrinsics to keep track of original LLVM types of the values
55// to be able to emit proper SPIR-V types eventually.
56//
57// TODO: consider removing spv.track.constant in favor of spv.assign.type.
58
59using namespace llvm;
60using namespace llvm::PatternMatch;
61
62#define DEBUG_TYPE "spirv-emit-intrinsics"
63
64static cl::opt<bool>
65 SpirvEmitOpNames("spirv-emit-op-names",
66 cl::desc("Emit OpName for all instructions"),
67 cl::init(false));
68
69namespace llvm::SPIRV {
70#define GET_BuiltinGroup_DECL
71#include "SPIRVGenTables.inc"
72} // namespace llvm::SPIRV
73
74namespace {
75// This class keeps track of which functions reference which global variables.
76class GlobalVariableUsers {
77 template <typename T1, typename T2>
78 using OneToManyMapTy = DenseMap<T1, SmallPtrSet<T2, 4>>;
79
80 OneToManyMapTy<const GlobalVariable *, const Function *> GlobalIsUsedByFun;
81
82 void collectGlobalUsers(
83 const GlobalVariable *GV,
84 OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
85 &GlobalIsUsedByGlobal) {
87 while (!Stack.empty()) {
88 const Value *V = Stack.pop_back_val();
89
90 if (const Instruction *I = dyn_cast<Instruction>(V)) {
91 GlobalIsUsedByFun[GV].insert(I->getFunction());
92 continue;
93 }
94
95 if (const GlobalVariable *UserGV = dyn_cast<GlobalVariable>(V)) {
96 GlobalIsUsedByGlobal[GV].insert(UserGV);
97 continue;
98 }
99
100 if (const Constant *C = dyn_cast<Constant>(V))
101 Stack.append(C->user_begin(), C->user_end());
102 }
103 }
104
105 bool propagateGlobalToGlobalUsers(
106 OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
107 &GlobalIsUsedByGlobal) {
109 bool Changed = false;
110 for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
111 OldUsersGlobals.assign(UserGlobals.begin(), UserGlobals.end());
112 for (const GlobalVariable *UserGV : OldUsersGlobals) {
113 auto It = GlobalIsUsedByGlobal.find(UserGV);
114 if (It == GlobalIsUsedByGlobal.end())
115 continue;
116 Changed |= set_union(UserGlobals, It->second);
117 }
118 }
119 return Changed;
120 }
121
122 void propagateGlobalToFunctionReferences(
123 OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
124 &GlobalIsUsedByGlobal) {
125 for (auto &[GV, UserGlobals] : GlobalIsUsedByGlobal) {
126 auto &UserFunctions = GlobalIsUsedByFun[GV];
127 for (const GlobalVariable *UserGV : UserGlobals) {
128 auto It = GlobalIsUsedByFun.find(UserGV);
129 if (It == GlobalIsUsedByFun.end())
130 continue;
131 set_union(UserFunctions, It->second);
132 }
133 }
134 }
135
136public:
137 void init(Module &M) {
138 // Collect which global variables are referenced by which global variables
139 // and which functions reference each global variables.
140 OneToManyMapTy<const GlobalVariable *, const GlobalVariable *>
141 GlobalIsUsedByGlobal;
142 GlobalIsUsedByFun.clear();
143 for (GlobalVariable &GV : M.globals())
144 collectGlobalUsers(&GV, GlobalIsUsedByGlobal);
145
146 // Compute indirect references by iterating until a fixed point is reached.
147 while (propagateGlobalToGlobalUsers(GlobalIsUsedByGlobal))
148 (void)0;
149
150 propagateGlobalToFunctionReferences(GlobalIsUsedByGlobal);
151 }
152
153 using FunctionSetType = typename decltype(GlobalIsUsedByFun)::mapped_type;
154 const FunctionSetType &
155 getTransitiveUserFunctions(const GlobalVariable &GV) const {
156 auto It = GlobalIsUsedByFun.find(&GV);
157 if (It != GlobalIsUsedByFun.end())
158 return It->second;
159
160 static const FunctionSetType Empty{};
161 return Empty;
162 }
163};
164
165static bool isaGEP(const Value *V) {
167}
168
169// If Ty is a byte-addressing type, return the multiplier for the offset.
170// Otherwise return std::nullopt.
171static std::optional<uint64_t> getByteAddressingMultiplier(Type *Ty) {
172 if (Ty == IntegerType::getInt8Ty(Ty->getContext())) {
173 return 1;
174 }
175 if (auto *AT = dyn_cast<ArrayType>(Ty)) {
176 if (AT->getElementType() == IntegerType::getInt8Ty(Ty->getContext())) {
177 return AT->getNumElements();
178 }
179 }
180 return std::nullopt;
181}
182
183class SPIRVEmitIntrinsics
184 : public ModulePass,
185 public InstVisitor<SPIRVEmitIntrinsics, Instruction *> {
186 const SPIRVTargetMachine &TM;
187 SPIRVGlobalRegistry *GR = nullptr;
188 Function *CurrF = nullptr;
189 bool TrackConstants = true;
190 bool HaveFunPtrs = false;
191 DenseMap<Instruction *, Constant *> AggrConsts;
192 DenseMap<Instruction *, Type *> AggrConstTypes;
193 SmallPtrSet<Instruction *, 0> AggrStores;
194 GlobalVariableUsers GVUsers;
195 SmallPtrSet<Value *, 0> Named;
196
197 // map of function declarations to <pointer arg index => element type>
198 DenseMap<Function *, SmallVector<std::pair<unsigned, Type *>>> FDeclPtrTys;
199
200 // a register of Instructions that don't have a complete type definition
201 bool CanTodoType = true;
202 unsigned TodoTypeSz = 0;
203 DenseMap<Value *, bool> TodoType;
204 void insertTodoType(Value *Op) {
205 // TODO: add isa<CallInst>(Op) to no-insert
206 if (CanTodoType && !isaGEP(Op)) {
207 auto It = TodoType.try_emplace(Op, true);
208 if (It.second)
209 ++TodoTypeSz;
210 }
211 }
212 void eraseTodoType(Value *Op) {
213 auto It = TodoType.find(Op);
214 if (It != TodoType.end() && It->second) {
215 It->second = false;
216 --TodoTypeSz;
217 }
218 }
219 bool isTodoType(Value *Op) {
220 if (isaGEP(Op))
221 return false;
222 auto It = TodoType.find(Op);
223 return It != TodoType.end() && It->second;
224 }
225 // a register of Instructions that were visited by deduceOperandElementType()
226 // to validate operand types with an instruction
227 SmallPtrSet<Instruction *, 0> TypeValidated;
228
229 // well known result types of builtins
230 enum WellKnownTypes { Event };
231
232 // deduce element type of untyped pointers
233 Type *deduceElementType(Value *I, bool UnknownElemTypeI8);
234 Type *deduceElementTypeHelper(Value *I, bool UnknownElemTypeI8);
235 Type *deduceElementTypeHelper(Value *I, SmallPtrSetImpl<Value *> &Visited,
236 bool UnknownElemTypeI8,
237 bool IgnoreKnownType = false);
238 Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
239 bool UnknownElemTypeI8);
240 Type *deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
241 SmallPtrSetImpl<Value *> &Visited,
242 bool UnknownElemTypeI8);
243 Type *deduceElementTypeByUsersDeep(Value *Op,
244 SmallPtrSetImpl<Value *> &Visited,
245 bool UnknownElemTypeI8);
246 void maybeAssignPtrType(Type *&Ty, Value *I, Type *RefTy,
247 bool UnknownElemTypeI8);
248
249 // deduce nested types of composites
250 Type *deduceNestedTypeHelper(User *U, bool UnknownElemTypeI8);
251 Type *deduceNestedTypeHelper(User *U, Type *Ty,
252 SmallPtrSetImpl<Value *> &Visited,
253 bool UnknownElemTypeI8);
254
255 // deduce Types of operands of the Instruction if possible
256 void
257 deduceOperandElementType(Instruction *I,
258 SmallPtrSetImpl<Instruction *> *IncompleteRets,
259 const SmallPtrSetImpl<Value *> *AskOps = nullptr,
260 bool IsPostprocessing = false);
261
262 void preprocessCompositeConstants(IRBuilder<> &B);
263 Value *lowerUndefOrPoison(Value *Op, IRBuilder<> &B, bool HasPoisonExt);
264 void preprocessUndefsAndPoisons(IRBuilder<> &B);
265 void insertCompositeAggregateArms(Instruction *I, IRBuilder<> &B);
266 void simplifyNullAddrSpaceCasts();
267
268 Type *reconstructType(Value *Op, bool UnknownElemTypeI8,
269 bool IsPostprocessing);
270
271 void replaceMemInstrUses(Instruction *Old, Instruction *New, IRBuilder<> &B);
272 void processInstrAfterVisit(Instruction *I, IRBuilder<> &B);
273 bool insertAssignPtrTypeIntrs(Instruction *I, IRBuilder<> &B,
274 bool UnknownElemTypeI8);
275 void insertAssignTypeIntrs(Instruction *I, IRBuilder<> &B);
276 void insertAssignPtrTypeTargetExt(TargetExtType *AssignedType, Value *V,
277 IRBuilder<> &B);
278 void replacePointerOperandWithPtrCast(Instruction *I, Value *Pointer,
279 Type *ExpectedElementType,
280 unsigned OperandToReplace,
281 IRBuilder<> &B);
282 void insertPtrCastOrAssignTypeInstr(Instruction *I, IRBuilder<> &B);
283 bool shouldTryToAddMemAliasingDecoration(Instruction *Inst);
284 void insertSpirvDecorations(Instruction *I, IRBuilder<> &B);
285 void insertConstantsForFPFastMathDefault(Module &M);
286 Value *buildSpvUndefComposite(Type *AggrTy, IRBuilder<> &B);
287 void reconstructAggregateReturns(Function &Func, IRBuilder<> &B);
288 void processGlobalValue(GlobalVariable &GV, IRBuilder<> &B);
289 void processParamTypes(Function *F, IRBuilder<> &B);
290 void processParamTypesByFunHeader(Function *F, IRBuilder<> &B);
291 Type *deduceFunParamElementType(Function *F, unsigned OpIdx);
292 Type *deduceFunParamElementType(Function *F, unsigned OpIdx,
293 SmallPtrSetImpl<Function *> &FVisited);
294
295 bool deduceOperandElementTypeCalledFunction(
296 CallInst *CI, SmallVector<std::pair<Value *, unsigned>> &Ops,
297 Type *&KnownElemTy, bool &Incomplete);
298 void deduceOperandElementTypeFunctionPointer(
299 CallInst *CI, SmallVector<std::pair<Value *, unsigned>> &Ops,
300 Type *&KnownElemTy, bool IsPostprocessing);
301 bool deduceOperandElementTypeFunctionRet(
302 Instruction *I, SmallPtrSetImpl<Instruction *> *IncompleteRets,
303 const SmallPtrSetImpl<Value *> *AskOps, bool IsPostprocessing,
304 Type *&KnownElemTy, Value *Op, Function *F);
305
306 CallInst *buildSpvPtrcast(Function *F, Value *Op, Type *ElemTy);
307 void replaceUsesOfWithSpvPtrcast(Value *Op, Type *ElemTy, Instruction *I,
308 DenseMap<Function *, CallInst *> Ptrcasts);
309 void propagateElemType(Value *Op, Type *ElemTy,
310 DenseSet<std::pair<Value *, Value *>> &VisitedSubst);
311 void
312 propagateElemTypeRec(Value *Op, Type *PtrElemTy, Type *CastElemTy,
313 DenseSet<std::pair<Value *, Value *>> &VisitedSubst);
314 void propagateElemTypeRec(Value *Op, Type *PtrElemTy, Type *CastElemTy,
315 DenseSet<std::pair<Value *, Value *>> &VisitedSubst,
316 SmallPtrSetImpl<Value *> &Visited,
317 DenseMap<Function *, CallInst *> Ptrcasts);
318
319 void replaceAllUsesWith(Value *Src, Value *Dest, bool DeleteOld = true);
320 void replaceAllUsesWithAndErase(IRBuilder<> &B, Instruction *Src,
321 Instruction *Dest, bool DeleteOld = true);
322
323 void applyDemangledPtrArgTypes(IRBuilder<> &B);
324
325 GetElementPtrInst *simplifyZeroLengthArrayGepInst(GetElementPtrInst *GEP);
326
327 bool runOnFunction(Function &F);
328 bool postprocessTypes(Module &M);
329 bool processFunctionPointers(Module &M);
330 void parseFunDeclarations(Module &M);
331 void useRoundingMode(ConstrainedFPIntrinsic *FPI, IRBuilder<> &B);
332 bool processMaskedMemIntrinsic(IntrinsicInst &I);
333 bool convertMaskedMemIntrinsics(Module &M);
334 void preprocessBoolVectorBitcasts(Function &F);
335
336 void emitUnstructuredLoopControls(Function &F, IRBuilder<> &B);
337
338 // Tries to walk the type accessed by the given GEP instruction.
339 // For each nested type access, one of the 2 callbacks is called:
340 // - OnLiteralIndexing when the index is a known constant value.
341 // Parameters:
342 // PointedType: the pointed type resulting of this indexing.
343 // If the parent type is an array, this is the index in the array.
344 // If the parent type is a struct, this is the field index.
345 // Index: index of the element in the parent type.
346 // - OnDynamnicIndexing when the index is a non-constant value.
347 // This callback is only called when indexing into an array.
348 // Parameters:
349 // ElementType: the type of the elements stored in the parent array.
350 // Offset: the Value* containing the byte offset into the array.
351 // Multiplier: a scaling factor for the offset.
352 // Return true if an error occurred during the walk, false otherwise.
353 bool walkLogicalAccessChain(
354 GetElementPtrInst &GEP,
355 const std::function<void(Type *PointedType, uint64_t Index)>
356 &OnLiteralIndexing,
357 const std::function<void(Type *ElementType, Value *Offset,
358 uint64_t Multiplier)> &OnDynamicIndexing);
359
360 bool walkLogicalAccessChainDynamic(
361 Type *CurType, Value *Operand, uint64_t Multiplier,
362 const std::function<void(Type *, uint64_t)> &OnLiteralIndexing,
363 const std::function<void(Type *, Value *, uint64_t)> &OnDynamicIndexing);
364
365 bool walkLogicalAccessChainConstant(
366 Type *CurType, uint64_t Offset,
367 const std::function<void(Type *, uint64_t)> &OnLiteralIndexing);
368
369 // Returns the type accessed using the given GEP instruction by relying
370 // on the GEP type.
371 // FIXME: GEP types are not supposed to be used to retrieve the pointed
372 // type. This must be fixed.
373 Type *getGEPType(GetElementPtrInst *GEP);
374
375 // Returns the type accessed using the given GEP instruction by walking
376 // the source type using the GEP indices.
377 // FIXME: without help from the frontend, this method cannot reliably retrieve
378 // the stored type, nor can robustly determine the depth of the type
379 // we are accessing.
380 Type *getGEPTypeLogical(GetElementPtrInst *GEP);
381
382 Instruction *buildLogicalAccessChainFromGEP(GetElementPtrInst &GEP);
383
384public:
385 static char ID;
386 SPIRVEmitIntrinsics(const SPIRVTargetMachine &TM) : ModulePass(ID), TM(TM) {}
387 Instruction *visitInstruction(Instruction &I) { return &I; }
388 Instruction *visitSwitchInst(SwitchInst &I);
389 Instruction *visitGetElementPtrInst(GetElementPtrInst &I);
390 Instruction *visitIntrinsicInst(IntrinsicInst &I);
391 Instruction *visitBitCastInst(BitCastInst &I);
392 Instruction *visitInsertElementInst(InsertElementInst &I);
393 Instruction *visitExtractElementInst(ExtractElementInst &I);
394 Instruction *visitInsertValueInst(InsertValueInst &I);
395 Instruction *visitExtractValueInst(ExtractValueInst &I);
396 Instruction *visitLoadInst(LoadInst &I);
397 Instruction *visitStoreInst(StoreInst &I);
398 Instruction *visitAllocaInst(AllocaInst &I);
399 Instruction *visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);
400 Instruction *visitUnreachableInst(UnreachableInst &I);
401 Instruction *visitCallInst(CallInst &I);
402
403 StringRef getPassName() const override { return "SPIRV emit intrinsics"; }
404
405 bool runOnModule(Module &M) override;
406
407 void getAnalysisUsage(AnalysisUsage &AU) const override {
408 ModulePass::getAnalysisUsage(AU);
409 }
410};
411
412bool isConvergenceIntrinsic(const Instruction *I) {
413 return match(I, m_AnyIntrinsic<Intrinsic::experimental_convergence_entry,
414 Intrinsic::experimental_convergence_loop,
415 Intrinsic::experimental_convergence_anchor>());
416}
417
418bool expectIgnoredInIRTranslation(const Instruction *I) {
419 return match(I, m_AnyIntrinsic<Intrinsic::invariant_start,
420 Intrinsic::spv_resource_handlefrombinding,
421 Intrinsic::spv_resource_getbasepointer,
422 Intrinsic::spv_resource_getpointer>());
423}
424
425// Returns the source pointer from `I` ignoring intermediate ptrcast.
426Value *getPointerRoot(Value *I) {
427 Value *V;
429 return getPointerRoot(V);
430 return I;
431}
432
433} // namespace
434
435char SPIRVEmitIntrinsics::ID = 0;
436
437INITIALIZE_PASS(SPIRVEmitIntrinsics, "spirv-emit-intrinsics",
438 "SPIRV emit intrinsics", false, false)
439
440static inline bool isAssignTypeInstr(const Instruction *I) {
442}
443
448
449static bool isAggrConstForceInt32(const Value *V) {
450 bool IsAggrZero =
451 isa<ConstantAggregateZero>(V) && !V->getType()->isVectorTy();
452 bool IsUndefAggregate = isa<UndefValue>(V) && V->getType()->isAggregateType();
453 return isa<ConstantArray>(V) || isa<ConstantStruct>(V) ||
454 isa<ConstantDataArray>(V) || IsAggrZero || IsUndefAggregate;
455}
456
462
464 if (isa<PHINode>(I))
465 B.SetInsertPoint(I->getParent()->getFirstNonPHIOrDbgOrAlloca());
466 else
467 B.SetInsertPoint(I);
468}
469
471 B.SetCurrentDebugLocation(I->getDebugLoc());
472 if (I->getType()->isVoidTy())
473 B.SetInsertPoint(I->getNextNode());
474 else
475 B.SetInsertPoint(*I->getInsertionPointAfterDef());
476}
477
483
484static inline void reportFatalOnTokenType(const Instruction *I) {
485 if (I->getType()->isTokenTy())
486 report_fatal_error("A token is encountered but SPIR-V without extensions "
487 "does not support token type",
488 false);
489}
490
492 if (!I->hasName() || I->getType()->isAggregateType() ||
493 expectIgnoredInIRTranslation(I))
494 return;
495
496 // We want to be conservative when adding the names because they can interfere
497 // with later optimizations.
498 bool KeepName = SpirvEmitOpNames;
499 if (!KeepName) {
500 if (isa<AllocaInst>(I)) {
501 KeepName = true;
502 } else if (auto *CI = dyn_cast<CallBase>(I)) {
503 Function *F = CI->getCalledFunction();
504 if (F && F->getName().starts_with("llvm.spv.alloca"))
505 KeepName = true;
506 }
507 }
508
509 if (!KeepName)
510 return;
511
514 LLVMContext &Ctx = I->getContext();
515 std::vector<Value *> Args = {
517 Ctx, MDNode::get(Ctx, MDString::get(Ctx, I->getName())))};
518 B.CreateIntrinsic(Intrinsic::spv_assign_name, {I->getType()}, Args);
519}
520
521void SPIRVEmitIntrinsics::replaceAllUsesWith(Value *Src, Value *Dest,
522 bool DeleteOld) {
523 GR->replaceAllUsesWith(Src, Dest, DeleteOld);
524 // Update uncomplete type records if any
525 if (isTodoType(Src)) {
526 if (DeleteOld)
527 eraseTodoType(Src);
528 insertTodoType(Dest);
529 }
530}
531
532void SPIRVEmitIntrinsics::replaceAllUsesWithAndErase(IRBuilder<> &B,
533 Instruction *Src,
534 Instruction *Dest,
535 bool DeleteOld) {
536 replaceAllUsesWith(Src, Dest, DeleteOld);
537 std::string Name = Src->hasName() ? Src->getName().str() : "";
538 Src->eraseFromParent();
539 if (!Name.empty()) {
540 Dest->setName(Name);
541 if (Named.insert(Dest).second)
542 emitAssignName(Dest, B);
543 }
544}
545
547 return SI && F->getCallingConv() == CallingConv::SPIR_KERNEL &&
548 isPointerTy(SI->getValueOperand()->getType()) &&
549 isa<Argument>(SI->getValueOperand());
550}
551
552// A pointer-typed local holds a pointer, so its deduced pointee must stay a
553// pointer.
555 using namespace PatternMatch;
556 V = V->stripPointerCasts();
557 if (auto *AI = dyn_cast<AllocaInst>(V))
558 return isUntypedPointerTy(AI->getAllocatedType());
559 return match(
561}
562
563// Maybe restore original function return type.
565 Type *Ty) {
567 if (!CI || CI->isIndirectCall() || CI->isInlineAsm() ||
569 return Ty;
570 if (Type *OriginalTy = GR->findMutated(CI->getCalledFunction()))
571 return OriginalTy;
572 return Ty;
573}
574
575// Reconstruct type with nested element types according to deduced type info.
576// Return nullptr if no detailed type info is available.
577Type *SPIRVEmitIntrinsics::reconstructType(Value *Op, bool UnknownElemTypeI8,
578 bool IsPostprocessing) {
579 Type *Ty = Op->getType();
580 if (auto *OpI = dyn_cast<Instruction>(Op)) {
581 Ty = restoreMutatedType(GR, OpI, Ty);
582 if (auto It = AggrConstTypes.find(OpI); It != AggrConstTypes.end())
583 Ty = It->second;
584 }
585 if (!isUntypedPointerTy(Ty))
586 return Ty;
587 // try to find the pointee type
588 if (Type *NestedTy = GR->findDeducedElementType(Op))
590 // not a pointer according to the type info (e.g., Event object)
591 CallInst *CI = GR->findAssignPtrTypeInstr(Op);
592 if (CI) {
593 MetadataAsValue *MD = cast<MetadataAsValue>(CI->getArgOperand(1));
594 return cast<ConstantAsMetadata>(MD->getMetadata())->getType();
595 }
596 if (UnknownElemTypeI8) {
597 if (!IsPostprocessing)
598 insertTodoType(Op);
599 return getTypedPointerWrapper(IntegerType::getInt8Ty(Op->getContext()),
601 }
602 return nullptr;
603}
604
605CallInst *SPIRVEmitIntrinsics::buildSpvPtrcast(Function *F, Value *Op,
606 Type *ElemTy) {
607 IRBuilder<> B(Op->getContext());
608 if (auto *OpI = dyn_cast<Instruction>(Op)) {
609 // spv_ptrcast's argument Op denotes an instruction that generates
610 // a value, and we may use getInsertionPointAfterDef()
612 } else if (auto *OpA = dyn_cast<Argument>(Op)) {
613 B.SetInsertPointPastAllocas(OpA->getParent());
614 B.SetCurrentDebugLocation(DebugLoc());
615 } else {
616 B.SetInsertPoint(F->getEntryBlock().getFirstNonPHIOrDbgOrAlloca());
617 }
618 Type *OpTy = Op->getType();
619 SmallVector<Type *, 2> Types = {OpTy, OpTy};
620 SmallVector<Value *, 2> Args = {Op, buildMD(getNormalizedPoisonValue(ElemTy)),
621 B.getInt32(getPointerAddressSpace(OpTy))};
622 CallInst *PtrCasted =
623 B.CreateIntrinsicWithoutFolding(Intrinsic::spv_ptrcast, {Types}, Args);
624 GR->buildAssignPtr(B, ElemTy, PtrCasted);
625 return PtrCasted;
626}
627
628void SPIRVEmitIntrinsics::replaceUsesOfWithSpvPtrcast(
629 Value *Op, Type *ElemTy, Instruction *I,
630 DenseMap<Function *, CallInst *> Ptrcasts) {
631 Function *F = I->getParent()->getParent();
632 CallInst *PtrCastedI = nullptr;
633 auto It = Ptrcasts.find(F);
634 if (It == Ptrcasts.end()) {
635 PtrCastedI = buildSpvPtrcast(F, Op, ElemTy);
636 Ptrcasts[F] = PtrCastedI;
637 } else {
638 PtrCastedI = It->second;
639 }
640 I->replaceUsesOfWith(Op, PtrCastedI);
641}
642
643void SPIRVEmitIntrinsics::propagateElemType(
644 Value *Op, Type *ElemTy,
645 DenseSet<std::pair<Value *, Value *>> &VisitedSubst) {
646 DenseMap<Function *, CallInst *> Ptrcasts;
647 SmallVector<User *> Users(Op->users());
648 for (auto *U : Users) {
649 if (!isa<Instruction>(U) || isSpvIntrinsic(U))
650 continue;
651 if (!VisitedSubst.insert(std::make_pair(U, Op)).second)
652 continue;
654 // If the instruction was validated already, we need to keep it valid by
655 // keeping current Op type.
656 if (isaGEP(UI) || TypeValidated.find(UI) != TypeValidated.end())
657 replaceUsesOfWithSpvPtrcast(Op, ElemTy, UI, Ptrcasts);
658 }
659}
660
661void SPIRVEmitIntrinsics::propagateElemTypeRec(
662 Value *Op, Type *PtrElemTy, Type *CastElemTy,
663 DenseSet<std::pair<Value *, Value *>> &VisitedSubst) {
664 SmallPtrSet<Value *, 0> Visited;
665 DenseMap<Function *, CallInst *> Ptrcasts;
666 propagateElemTypeRec(Op, PtrElemTy, CastElemTy, VisitedSubst, Visited,
667 std::move(Ptrcasts));
668}
669
670void SPIRVEmitIntrinsics::propagateElemTypeRec(
671 Value *Op, Type *PtrElemTy, Type *CastElemTy,
672 DenseSet<std::pair<Value *, Value *>> &VisitedSubst,
673 SmallPtrSetImpl<Value *> &Visited,
674 DenseMap<Function *, CallInst *> Ptrcasts) {
675 if (!Visited.insert(Op).second)
676 return;
677 SmallVector<User *> Users(Op->users());
678 for (auto *U : Users) {
679 if (!isa<Instruction>(U) || isSpvIntrinsic(U))
680 continue;
681 if (!VisitedSubst.insert(std::make_pair(U, Op)).second)
682 continue;
684 // If the instruction was validated already, we need to keep it valid by
685 // keeping current Op type.
686 if (isaGEP(UI) || TypeValidated.find(UI) != TypeValidated.end())
687 replaceUsesOfWithSpvPtrcast(Op, CastElemTy, UI, Ptrcasts);
688 }
689}
690
691// Set element pointer type to the given value of ValueTy and tries to
692// specify this type further (recursively) by Operand value, if needed.
693
694Type *
695SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(Type *ValueTy, Value *Operand,
696 bool UnknownElemTypeI8) {
697 SmallPtrSet<Value *, 0> Visited;
698 return deduceElementTypeByValueDeep(ValueTy, Operand, Visited,
699 UnknownElemTypeI8);
700}
701
702Type *SPIRVEmitIntrinsics::deduceElementTypeByValueDeep(
703 Type *ValueTy, Value *Operand, SmallPtrSetImpl<Value *> &Visited,
704 bool UnknownElemTypeI8) {
705 Type *Ty = ValueTy;
706 if (Operand) {
707 if (auto *PtrTy = dyn_cast<PointerType>(Ty)) {
708 if (Type *NestedTy =
709 deduceElementTypeHelper(Operand, Visited, UnknownElemTypeI8))
710 Ty = getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
711 } else {
712 Ty = deduceNestedTypeHelper(dyn_cast<User>(Operand), Ty, Visited,
713 UnknownElemTypeI8);
714 }
715 }
716 return Ty;
717}
718
719// Traverse User instructions to deduce an element pointer type of the operand.
720Type *SPIRVEmitIntrinsics::deduceElementTypeByUsersDeep(
721 Value *Op, SmallPtrSetImpl<Value *> &Visited, bool UnknownElemTypeI8) {
722 if (!Op || !isPointerTy(Op->getType()) || isa<ConstantPointerNull>(Op) ||
724 return nullptr;
725
726 if (auto ElemTy = getPointeeType(Op->getType()))
727 return ElemTy;
728
729 // maybe we already know operand's element type
730 if (Type *KnownTy = GR->findDeducedElementType(Op))
731 return KnownTy;
732
733 for (User *OpU : Op->users()) {
734 if (Instruction *Inst = dyn_cast<Instruction>(OpU)) {
735 if (Type *Ty = deduceElementTypeHelper(Inst, Visited, UnknownElemTypeI8))
736 return Ty;
737 }
738 }
739 return nullptr;
740}
741
742// Implements what we know in advance about intrinsics and builtin calls
743// TODO: consider feasibility of this particular case to be generalized by
744// encoding knowledge about intrinsics and builtin calls by corresponding
745// specification rules
747 Function *CalledF, unsigned OpIdx) {
748 if ((DemangledName.starts_with("__spirv_ocl_printf(") ||
749 DemangledName.starts_with("printf(")) &&
750 OpIdx == 0)
751 return IntegerType::getInt8Ty(CalledF->getContext());
752 return nullptr;
753}
754
755// Deduce and return a successfully deduced Type of the Instruction,
756// or nullptr otherwise.
757Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(Value *I,
758 bool UnknownElemTypeI8) {
759 SmallPtrSet<Value *, 0> Visited;
760 return deduceElementTypeHelper(I, Visited, UnknownElemTypeI8);
761}
762
763void SPIRVEmitIntrinsics::maybeAssignPtrType(Type *&Ty, Value *Op, Type *RefTy,
764 bool UnknownElemTypeI8) {
765 if (isUntypedPointerTy(RefTy)) {
766 if (!UnknownElemTypeI8)
767 return;
768 insertTodoType(Op);
770 return;
771 }
772 Ty = RefTy;
773}
774
775bool SPIRVEmitIntrinsics::walkLogicalAccessChainDynamic(
776 Type *CurType, Value *Operand, uint64_t Multiplier,
777 const std::function<void(Type *, uint64_t)> &OnLiteralIndexing,
778 const std::function<void(Type *, Value *, uint64_t)> &OnDynamicIndexing) {
779 // Dynamic indexing into a struct is not possible.
780 // We know that we must be accessing the first element
781 // of the struct if the current type is a struct.
782 // Try to find the first array type that is at offset 0 in the struct.
783 while (auto *ST = dyn_cast<StructType>(CurType)) {
784 if (ST->getNumElements() == 0)
785 break;
786 CurType = ST->getElementType(0);
787 OnLiteralIndexing(CurType, 0);
788 }
789
790 assert(CurType);
791 ArrayType *AT = dyn_cast<ArrayType>(CurType);
792 // Operand is not constant. Either we have an array and accept it, or we
793 // give up.
794 if (AT)
795 OnDynamicIndexing(AT->getElementType(), Operand, Multiplier);
796 return AT == nullptr;
797}
798
799bool SPIRVEmitIntrinsics::walkLogicalAccessChainConstant(
800 Type *CurType, uint64_t Offset,
801 const std::function<void(Type *, uint64_t)> &OnLiteralIndexing) {
802 auto &DL = CurrF->getDataLayout();
803
804 do {
805 if (ArrayType *AT = dyn_cast<ArrayType>(CurType)) {
806 uint64_t EltTypeSize = DL.getTypeAllocSize(AT->getElementType());
807 assert(Offset < AT->getNumElements() * EltTypeSize);
808 uint64_t Index = Offset / EltTypeSize;
809 Offset = Offset - (Index * EltTypeSize);
810 CurType = AT->getElementType();
811 OnLiteralIndexing(CurType, Index);
812 } else if (StructType *ST = dyn_cast<StructType>(CurType)) {
813 uint32_t StructSize = DL.getTypeSizeInBits(ST) / 8;
814 assert(Offset < StructSize);
815 (void)StructSize;
816 const auto &STL = DL.getStructLayout(ST);
817 unsigned Element = STL->getElementContainingOffset(Offset);
818 Offset -= STL->getElementOffset(Element);
819 CurType = ST->getElementType(Element);
820 OnLiteralIndexing(CurType, Element);
821 } else if (auto *VT = dyn_cast<FixedVectorType>(CurType)) {
822 Type *EltTy = VT->getElementType();
823 TypeSize EltSizeBits = DL.getTypeSizeInBits(EltTy);
824 assert(EltSizeBits % 8 == 0 &&
825 "Element type size in bits must be a multiple of 8.");
826 uint32_t EltTypeSize = EltSizeBits / 8;
827 assert(Offset < VT->getNumElements() * EltTypeSize);
828 uint64_t Index = Offset / EltTypeSize;
829 Offset -= Index * EltTypeSize;
830 CurType = EltTy;
831 OnLiteralIndexing(CurType, Index);
832 } else {
833 // Unknown composite kind; give up.
834 return true;
835 }
836 } while (Offset > 0);
837
838 return false;
839}
840
841bool SPIRVEmitIntrinsics::walkLogicalAccessChain(
842 GetElementPtrInst &GEP,
843 const std::function<void(Type *, uint64_t)> &OnLiteralIndexing,
844 const std::function<void(Type *, Value *, uint64_t)> &OnDynamicIndexing) {
845 // We only rewrite byte-addressing GEP. Other should be left as-is.
846 // Valid byte-addressing GEP must always have a single index.
847 std::optional<uint64_t> MultiplierOpt =
848 getByteAddressingMultiplier(GEP.getSourceElementType());
849 assert(MultiplierOpt && "We only rewrite byte-addressing GEP");
850 uint64_t Multiplier = *MultiplierOpt;
851 assert(GEP.getNumIndices() == 1);
852
853 Value *Src = getPointerRoot(GEP.getPointerOperand());
854 Type *CurType = deduceElementType(Src, true);
855
856 Value *Operand = *GEP.idx_begin();
857 if (ConstantInt *CI = dyn_cast<ConstantInt>(Operand))
858 return walkLogicalAccessChainConstant(
859 CurType, CI->getZExtValue() * Multiplier, OnLiteralIndexing);
860
861 return walkLogicalAccessChainDynamic(CurType, Operand, Multiplier,
862 OnLiteralIndexing, OnDynamicIndexing);
863}
864
866SPIRVEmitIntrinsics::buildLogicalAccessChainFromGEP(GetElementPtrInst &GEP) {
867 auto &DL = CurrF->getDataLayout();
868 IRBuilder<> B(GEP.getParent());
869 B.SetInsertPoint(&GEP);
870
871 std::vector<Value *> Indices;
872 Indices.push_back(ConstantInt::get(
873 IntegerType::getInt32Ty(CurrF->getContext()), 0, /* Signed= */ false));
874 walkLogicalAccessChain(
875 GEP,
876 [&Indices, &B](Type *EltType, uint64_t Index) {
877 Indices.push_back(
878 ConstantInt::get(B.getInt64Ty(), Index, /* Signed= */ false));
879 },
880 [&Indices, &B, &DL, this](Type *EltType, Value *Offset,
881 uint64_t Multiplier) {
882 Value *Index = nullptr;
883 uint32_t EltTypeSize = DL.getTypeSizeInBits(EltType) / 8;
884 assert(Multiplier != 0);
885 if (Multiplier == EltTypeSize) {
886 Index = Offset;
887 } else if (EltTypeSize % Multiplier == 0) {
888 Index =
889 B.CreateUDiv(Offset, ConstantInt::get(Offset->getType(),
890 EltTypeSize / Multiplier,
891 /* Signed= */ false));
892 } else {
893 Index = B.CreateMul(Offset,
894 ConstantInt::get(Offset->getType(), Multiplier,
895 /* Signed= */ false));
896 insertAssignTypeIntrs(cast<Instruction>(Index), B);
897 Index = B.CreateUDiv(Index,
898 ConstantInt::get(Offset->getType(), EltTypeSize,
899 /* Signed= */ false));
900 }
901 insertAssignTypeIntrs(cast<Instruction>(Index), B);
902 Indices.push_back(Index);
903 });
904
905 SmallVector<Type *, 2> Types = {GEP.getType(), GEP.getOperand(0)->getType()};
906 SmallVector<Value *, 4> Args;
907 Args.push_back(B.getInt1(GEP.isInBounds()));
908 Args.push_back(GEP.getOperand(0));
909 llvm::append_range(Args, Indices);
910 Instruction *NewI =
911 B.CreateIntrinsicWithoutFolding(Intrinsic::spv_gep, {Types}, {Args});
912 replaceAllUsesWithAndErase(B, &GEP, NewI);
913 return NewI;
914}
915
916Type *SPIRVEmitIntrinsics::getGEPTypeLogical(GetElementPtrInst *GEP) {
917
918 Type *CurType = GEP->getResultElementType();
919
920 bool Interrupted = walkLogicalAccessChain(
921 *GEP, [&CurType](Type *EltType, uint64_t Index) { CurType = EltType; },
922 [&CurType](Type *EltType, Value *Index, uint64_t) { CurType = EltType; });
923
924 return Interrupted ? GEP->getResultElementType() : CurType;
925}
926
927Type *SPIRVEmitIntrinsics::getGEPType(GetElementPtrInst *Ref) {
928 if (getByteAddressingMultiplier(Ref->getSourceElementType()) &&
930 return getGEPTypeLogical(Ref);
931 }
932
933 Type *Ty = nullptr;
934 // TODO: not sure if GetElementPtrInst::getTypeAtIndex() does anything
935 // useful here
936 if (isNestedPointer(Ref->getSourceElementType())) {
937 Ty = Ref->getSourceElementType();
938 for (Use &U : drop_begin(Ref->indices()))
939 Ty = GetElementPtrInst::getTypeAtIndex(Ty, U.get());
940 } else {
941 Ty = Ref->getResultElementType();
942 }
943 return Ty;
944}
945
946Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
947 Value *I, SmallPtrSetImpl<Value *> &Visited, bool UnknownElemTypeI8,
948 bool IgnoreKnownType) {
949 // allow to pass nullptr as an argument
950 if (!I)
951 return nullptr;
952
953 // maybe already known
954 if (!IgnoreKnownType)
955 if (Type *KnownTy = GR->findDeducedElementType(I))
956 return KnownTy;
957
958 // maybe a cycle
959 if (!Visited.insert(I).second)
960 return nullptr;
961
962 // fallback value in case when we fail to deduce a type
963 Type *Ty = nullptr;
964 // look for known basic patterns of type inference
965 if (auto *Ref = dyn_cast<AllocaInst>(I)) {
966 maybeAssignPtrType(Ty, I, Ref->getAllocatedType(), UnknownElemTypeI8);
967 } else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
968 Ty = getGEPType(Ref);
969 } else if (auto *SGEP = dyn_cast<StructuredGEPInst>(I)) {
970 Ty = SGEP->getResultElementType();
971 } else if (auto *Ref = dyn_cast<LoadInst>(I)) {
972 Value *Op = Ref->getPointerOperand();
973 Type *KnownTy = GR->findDeducedElementType(Op);
974 if (!KnownTy)
975 KnownTy = Op->getType();
976 if (Type *ElemTy = getPointeeType(KnownTy))
977 maybeAssignPtrType(Ty, I, ElemTy, UnknownElemTypeI8);
978 } else if (auto *Ref = dyn_cast<GlobalValue>(I)) {
979 if (auto *Fn = dyn_cast<Function>(Ref)) {
980 Ty = SPIRV::getOriginalFunctionType(*Fn);
981 GR->addDeducedElementType(I, Ty);
982 } else {
983 Ty = deduceElementTypeByValueDeep(
984 Ref->getValueType(),
985 Ref->getNumOperands() > 0 ? Ref->getOperand(0) : nullptr, Visited,
986 UnknownElemTypeI8);
987 }
988 } else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) {
989 Type *RefTy = deduceElementTypeHelper(Ref->getPointerOperand(), Visited,
990 UnknownElemTypeI8);
991 maybeAssignPtrType(Ty, I, RefTy, UnknownElemTypeI8);
992 } else if (auto *Ref = dyn_cast<IntToPtrInst>(I)) {
993 maybeAssignPtrType(Ty, I, Ref->getDestTy(), UnknownElemTypeI8);
994 } else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
995 if (Type *Src = Ref->getSrcTy(), *Dest = Ref->getDestTy();
996 isPointerTy(Src) && isPointerTy(Dest))
997 Ty = deduceElementTypeHelper(Ref->getOperand(0), Visited,
998 UnknownElemTypeI8);
999 } else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) {
1000 Value *Op = Ref->getNewValOperand();
1001 if (isPointerTy(Op->getType()))
1002 Ty = deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8);
1003 } else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) {
1004 Value *Op = Ref->getValOperand();
1005 if (isPointerTy(Op->getType()))
1006 Ty = deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8);
1007 } else if (auto *Ref = dyn_cast<PHINode>(I)) {
1008 Type *BestTy = nullptr;
1009 unsigned MaxN = 1;
1010 DenseMap<Type *, unsigned> PhiTys;
1011 for (int i = Ref->getNumIncomingValues() - 1; i >= 0; --i) {
1012 Ty = deduceElementTypeByUsersDeep(Ref->getIncomingValue(i), Visited,
1013 UnknownElemTypeI8);
1014 if (!Ty)
1015 continue;
1016 auto It = PhiTys.try_emplace(Ty, 1);
1017 if (!It.second) {
1018 ++It.first->second;
1019 if (It.first->second > MaxN) {
1020 MaxN = It.first->second;
1021 BestTy = Ty;
1022 }
1023 }
1024 }
1025 if (BestTy)
1026 Ty = BestTy;
1027 } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
1028 for (Value *Op : {Ref->getTrueValue(), Ref->getFalseValue()}) {
1029 Ty = deduceElementTypeByUsersDeep(Op, Visited, UnknownElemTypeI8);
1030 if (Ty)
1031 break;
1032 }
1033 } else if (auto *CI = dyn_cast<CallInst>(I)) {
1034 static StringMap<unsigned> ResTypeByArg = {
1035 {"to_global", 0},
1036 {"to_local", 0},
1037 {"to_private", 0},
1038 {"__spirv_GenericCastToPtr_ToGlobal", 0},
1039 {"__spirv_GenericCastToPtr_ToLocal", 0},
1040 {"__spirv_GenericCastToPtr_ToPrivate", 0},
1041 {"__spirv_GenericCastToPtrExplicit_ToGlobal", 0},
1042 {"__spirv_GenericCastToPtrExplicit_ToLocal", 0},
1043 {"__spirv_GenericCastToPtrExplicit_ToPrivate", 0}};
1044 // TODO: maybe improve performance by caching demangled names
1045
1046 auto *II = dyn_cast<IntrinsicInst>(I);
1047 if (II && (II->getIntrinsicID() == Intrinsic::spv_resource_getbasepointer ||
1048 II->getIntrinsicID() == Intrinsic::spv_resource_getpointer)) {
1049 auto *HandleType = cast<TargetExtType>(II->getOperand(0)->getType());
1050 if (HandleType->getTargetExtName() == "spirv.Image" ||
1051 HandleType->getTargetExtName() == "spirv.SignedImage") {
1052 for (User *U : II->users()) {
1053 Ty = cast<Instruction>(U)->getAccessType();
1054 if (Ty)
1055 break;
1056 }
1057 } else if (HandleType->getTargetExtName() == "spirv.VulkanBuffer") {
1058 // This call is supposed to index into an array
1059 Ty = HandleType->getTypeParameter(0);
1060 if (II->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
1061 if (Ty->isArrayTy())
1062 Ty = Ty->getArrayElementType();
1063 else {
1064 assert(Ty && Ty->isStructTy());
1065 uint32_t Index =
1066 cast<ConstantInt>(II->getOperand(1))->getZExtValue();
1067 Ty = cast<StructType>(Ty)->getElementType(Index);
1068 }
1069 }
1071 } else {
1072 llvm_unreachable("Unknown handle type for spv_resource_getpointer.");
1073 }
1074 } else if (II && II->getIntrinsicID() ==
1075 Intrinsic::spv_generic_cast_to_ptr_explicit) {
1076 Ty = deduceElementTypeHelper(CI->getArgOperand(0), Visited,
1077 UnknownElemTypeI8);
1078 } else if (Function *CalledF = CI->getCalledFunction()) {
1079 std::string DemangledName =
1080 getOclOrSpirvBuiltinDemangledName(CalledF->getName());
1081 if (DemangledName.length() > 0)
1082 DemangledName = SPIRV::lookupBuiltinNameHelper(DemangledName);
1083 auto AsArgIt = ResTypeByArg.find(DemangledName);
1084 if (AsArgIt != ResTypeByArg.end())
1085 Ty = deduceElementTypeHelper(CI->getArgOperand(AsArgIt->second),
1086 Visited, UnknownElemTypeI8);
1087 else if (Type *KnownRetTy = GR->findDeducedElementType(CalledF))
1088 Ty = KnownRetTy;
1089 }
1090 }
1091
1092 // remember the found relationship
1093 if (Ty && !IgnoreKnownType) {
1094 // specify nested types if needed, otherwise return unchanged
1096 }
1097
1098 return Ty;
1099}
1100
1101// Re-create a type of the value if it has untyped pointer fields, also nested.
1102// Return the original value type if no corrections of untyped pointer
1103// information is found or needed.
1104Type *SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U,
1105 bool UnknownElemTypeI8) {
1106 SmallPtrSet<Value *, 0> Visited;
1107 return deduceNestedTypeHelper(U, U->getType(), Visited, UnknownElemTypeI8);
1108}
1109
1110Type *
1111SPIRVEmitIntrinsics::deduceNestedTypeHelper(User *U, Type *OrigTy,
1112 SmallPtrSetImpl<Value *> &Visited,
1113 bool UnknownElemTypeI8) {
1114 if (!U)
1115 return OrigTy;
1116
1117 // maybe already known
1118 if (Type *KnownTy = GR->findDeducedCompositeType(U))
1119 return KnownTy;
1120
1121 // maybe a cycle
1122 if (!Visited.insert(U).second)
1123 return OrigTy;
1124
1125 if (isa<StructType>(OrigTy)) {
1127 bool Change = false;
1128 for (unsigned i = 0; i < U->getNumOperands(); ++i) {
1129 Value *Op = U->getOperand(i);
1130 assert(Op && "Operands should not be null.");
1131 Type *OpTy = Op->getType();
1132 Type *Ty = OpTy;
1133 if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
1134 if (Type *NestedTy =
1135 deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8))
1136 Ty = getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
1137 } else {
1138 Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited,
1139 UnknownElemTypeI8);
1140 }
1141 Tys.push_back(Ty);
1142 Change |= Ty != OpTy;
1143 }
1144 if (Change) {
1145 Type *NewTy = StructType::create(Tys);
1146 GR->addDeducedCompositeType(U, NewTy);
1147 return NewTy;
1148 }
1149 } else if (auto *ArrTy = dyn_cast<ArrayType>(OrigTy)) {
1150 if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) {
1151 Type *OpTy = ArrTy->getElementType();
1152 Type *Ty = OpTy;
1153 if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
1154 if (Type *NestedTy =
1155 deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8))
1156 Ty = getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
1157 } else {
1158 Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited,
1159 UnknownElemTypeI8);
1160 }
1161 if (Ty != OpTy) {
1162 Type *NewTy = ArrayType::get(Ty, ArrTy->getNumElements());
1163 GR->addDeducedCompositeType(U, NewTy);
1164 return NewTy;
1165 }
1166 }
1167 } else if (auto *VecTy = dyn_cast<VectorType>(OrigTy)) {
1168 if (Value *Op = U->getNumOperands() > 0 ? U->getOperand(0) : nullptr) {
1169 Type *OpTy = VecTy->getElementType();
1170 Type *Ty = OpTy;
1171 if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
1172 if (Type *NestedTy =
1173 deduceElementTypeHelper(Op, Visited, UnknownElemTypeI8))
1174 Ty = getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
1175 } else {
1176 Ty = deduceNestedTypeHelper(dyn_cast<User>(Op), OpTy, Visited,
1177 UnknownElemTypeI8);
1178 }
1179 if (Ty != OpTy) {
1180 Type *NewTy = VectorType::get(Ty, VecTy->getElementCount());
1182 return NewTy;
1183 }
1184 }
1185 }
1186
1187 return OrigTy;
1188}
1189
1190Type *SPIRVEmitIntrinsics::deduceElementType(Value *I, bool UnknownElemTypeI8) {
1191 if (Type *Ty = deduceElementTypeHelper(I, UnknownElemTypeI8))
1192 return Ty;
1193 if (!UnknownElemTypeI8)
1194 return nullptr;
1195 insertTodoType(I);
1196 return IntegerType::getInt8Ty(I->getContext());
1197}
1198
1200 Value *PointerOperand) {
1201 Type *PointeeTy = GR->findDeducedElementType(PointerOperand);
1202 if (PointeeTy && !isUntypedPointerTy(PointeeTy))
1203 return nullptr;
1204 auto *PtrTy = dyn_cast<PointerType>(I->getType());
1205 if (!PtrTy)
1206 return I->getType();
1207 if (Type *NestedTy = GR->findDeducedElementType(I))
1208 return getTypedPointerWrapper(NestedTy, PtrTy->getAddressSpace());
1209 return nullptr;
1210}
1211
1212// Try to deduce element type for a call base. Returns false if this is an
1213// indirect function invocation, and true otherwise.
1214bool SPIRVEmitIntrinsics::deduceOperandElementTypeCalledFunction(
1215 CallInst *CI, SmallVector<std::pair<Value *, unsigned>> &Ops,
1216 Type *&KnownElemTy, bool &Incomplete) {
1217 Function *CalledF = CI->getCalledFunction();
1218 if (!CalledF)
1219 return false;
1220 std::string DemangledName =
1222 if (DemangledName.length() > 0 &&
1223 !StringRef(DemangledName).starts_with("llvm.")) {
1224 const SPIRVSubtarget &ST = TM.getSubtarget<SPIRVSubtarget>(*CalledF);
1225 auto [Grp, Opcode, ExtNo] = SPIRV::mapBuiltinToOpcode(
1226 DemangledName, ST.getPreferredInstructionSet());
1227 if (Opcode == SPIRV::OpGroupAsyncCopy) {
1228 for (unsigned i = 0, PtrCnt = 0; i < CI->arg_size() && PtrCnt < 2; ++i) {
1229 Value *Op = CI->getArgOperand(i);
1230 if (!isPointerTy(Op->getType()))
1231 continue;
1232 ++PtrCnt;
1233 if (Type *ElemTy = GR->findDeducedElementType(Op))
1234 KnownElemTy = ElemTy; // src will rewrite dest if both are defined
1235 Ops.push_back(std::make_pair(Op, i));
1236 }
1237 } else if (Grp == SPIRV::Atomic || Grp == SPIRV::AtomicFloating) {
1238 if (CI->arg_size() == 0)
1239 return true;
1240 Value *Op = CI->getArgOperand(0);
1241 if (!isPointerTy(Op->getType()))
1242 return true;
1243 switch (Opcode) {
1244 case SPIRV::OpAtomicFAddEXT:
1245 case SPIRV::OpAtomicFMinEXT:
1246 case SPIRV::OpAtomicFMaxEXT:
1247 case SPIRV::OpAtomicLoad:
1248 case SPIRV::OpAtomicCompareExchangeWeak:
1249 case SPIRV::OpAtomicCompareExchange:
1250 case SPIRV::OpAtomicExchange:
1251 case SPIRV::OpAtomicIAdd:
1252 case SPIRV::OpAtomicISub:
1253 case SPIRV::OpAtomicOr:
1254 case SPIRV::OpAtomicXor:
1255 case SPIRV::OpAtomicAnd:
1256 case SPIRV::OpAtomicUMin:
1257 case SPIRV::OpAtomicUMax:
1258 case SPIRV::OpAtomicSMin:
1259 case SPIRV::OpAtomicSMax: {
1260 KnownElemTy = isPointerTy(CI->getType()) ? getAtomicElemTy(GR, CI, Op)
1261 : CI->getType();
1262 if (!KnownElemTy)
1263 return true;
1264 Incomplete = isTodoType(Op);
1265 Ops.push_back(std::make_pair(Op, 0));
1266 } break;
1267 case SPIRV::OpAtomicStore: {
1268 if (CI->arg_size() < 4)
1269 return true;
1270 Value *ValOp = CI->getArgOperand(3);
1271 KnownElemTy = isPointerTy(ValOp->getType())
1272 ? getAtomicElemTy(GR, CI, Op)
1273 : ValOp->getType();
1274 if (!KnownElemTy)
1275 return true;
1276 Incomplete = isTodoType(Op);
1277 Ops.push_back(std::make_pair(Op, 0));
1278 } break;
1279 }
1280 }
1281 }
1282 return true;
1283}
1284
1285// Try to deduce element type for a function pointer.
1286void SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionPointer(
1287 CallInst *CI, SmallVector<std::pair<Value *, unsigned>> &Ops,
1288 Type *&KnownElemTy, bool IsPostprocessing) {
1289 Value *Op = CI->getCalledOperand();
1290 if (!Op || !isPointerTy(Op->getType()))
1291 return;
1292 Ops.push_back(std::make_pair(Op, std::numeric_limits<unsigned>::max()));
1293 FunctionType *FTy = SPIRV::getOriginalFunctionType(*CI);
1294 bool IsNewFTy = false, IsIncomplete = false;
1296 for (auto &&[ParmIdx, Arg] : llvm::enumerate(CI->args())) {
1297 Type *ArgTy = Arg->getType();
1298 if (ArgTy->isPointerTy()) {
1299 if (Type *ElemTy = GR->findDeducedElementType(Arg)) {
1300 IsNewFTy = true;
1301 ArgTy = getTypedPointerWrapper(ElemTy, getPointerAddressSpace(ArgTy));
1302 if (isTodoType(Arg))
1303 IsIncomplete = true;
1304 } else {
1305 IsIncomplete = true;
1306 }
1307 } else {
1308 ArgTy = FTy->getFunctionParamType(ParmIdx);
1309 }
1310 ArgTys.push_back(ArgTy);
1311 }
1312 Type *RetTy = FTy->getReturnType();
1313 if (CI->getType()->isPointerTy()) {
1314 if (Type *ElemTy = GR->findDeducedElementType(CI)) {
1315 IsNewFTy = true;
1316 RetTy =
1318 if (isTodoType(CI))
1319 IsIncomplete = true;
1320 } else {
1321 IsIncomplete = true;
1322 }
1323 }
1324 if (!IsPostprocessing && IsIncomplete)
1325 insertTodoType(Op);
1326 KnownElemTy =
1327 IsNewFTy ? FunctionType::get(RetTy, ArgTys, FTy->isVarArg()) : FTy;
1328}
1329
1330bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet(
1331 Instruction *I, SmallPtrSetImpl<Instruction *> *IncompleteRets,
1332 const SmallPtrSetImpl<Value *> *AskOps, bool IsPostprocessing,
1333 Type *&KnownElemTy, Value *Op, Function *F) {
1334 KnownElemTy = GR->findDeducedElementType(F);
1335 if (KnownElemTy)
1336 return false;
1337 if (Type *OpElemTy = GR->findDeducedElementType(Op)) {
1338 OpElemTy = normalizeType(OpElemTy);
1339 GR->addDeducedElementType(F, OpElemTy);
1340 GR->addReturnType(
1341 F, TypedPointerType::get(OpElemTy,
1342 getPointerAddressSpace(F->getReturnType())));
1343 // non-recursive update of types in function uses
1344 DenseSet<std::pair<Value *, Value *>> VisitedSubst{std::make_pair(I, Op)};
1345 for (User *U : F->users()) {
1346 CallInst *CI = dyn_cast<CallInst>(U);
1347 if (!CI || CI->getCalledFunction() != F)
1348 continue;
1349 if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(CI)) {
1350 if (Type *PrevElemTy = GR->findDeducedElementType(CI)) {
1351 GR->updateAssignType(AssignCI, CI,
1352 getNormalizedPoisonValue(OpElemTy));
1353 propagateElemType(CI, PrevElemTy, VisitedSubst);
1354 }
1355 }
1356 }
1357 // Non-recursive update of types in the function uncomplete returns.
1358 // This may happen just once per a function, the latch is a pair of
1359 // findDeducedElementType(F) / addDeducedElementType(F, ...).
1360 // With or without the latch it is a non-recursive call due to
1361 // IncompleteRets set to nullptr in this call.
1362 if (IncompleteRets)
1363 for (Instruction *IncompleteRetI : *IncompleteRets)
1364 deduceOperandElementType(IncompleteRetI, nullptr, AskOps,
1365 IsPostprocessing);
1366 } else if (IncompleteRets) {
1367 IncompleteRets->insert(I);
1368 }
1369 TypeValidated.insert(I);
1370 return true;
1371}
1372
1373// If the Instruction has Pointer operands with unresolved types, this function
1374// tries to deduce them. If the Instruction has Pointer operands with known
1375// types which differ from expected, this function tries to insert a bitcast to
1376// resolve the issue.
1377void SPIRVEmitIntrinsics::deduceOperandElementType(
1378 Instruction *I, SmallPtrSetImpl<Instruction *> *IncompleteRets,
1379 const SmallPtrSetImpl<Value *> *AskOps, bool IsPostprocessing) {
1381 Type *KnownElemTy = nullptr;
1382 bool Incomplete = false;
1383 // look for known basic patterns of type inference
1384 if (auto *Ref = dyn_cast<PHINode>(I)) {
1385 if (!isPointerTy(I->getType()) ||
1386 !(KnownElemTy = GR->findDeducedElementType(I)))
1387 return;
1388 Incomplete = isTodoType(I);
1389 for (unsigned i = 0; i < Ref->getNumIncomingValues(); i++) {
1390 Value *Op = Ref->getIncomingValue(i);
1391 if (isPointerTy(Op->getType()))
1392 Ops.push_back(std::make_pair(Op, i));
1393 }
1394 } else if (auto *Ref = dyn_cast<AddrSpaceCastInst>(I)) {
1395 KnownElemTy = GR->findDeducedElementType(I);
1396 if (!KnownElemTy)
1397 return;
1398 Incomplete = isTodoType(I);
1399 Ops.push_back(std::make_pair(Ref->getPointerOperand(), 0));
1400 } else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
1401 if (!isPointerTy(I->getType()))
1402 return;
1403 KnownElemTy = GR->findDeducedElementType(I);
1404 if (!KnownElemTy)
1405 return;
1406 Incomplete = isTodoType(I);
1407 Ops.push_back(std::make_pair(Ref->getOperand(0), 0));
1408 } else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
1409 if (GR->findDeducedElementType(Ref->getPointerOperand()))
1410 return;
1411 KnownElemTy = Ref->getSourceElementType();
1412 Ops.push_back(std::make_pair(Ref->getPointerOperand(),
1414 } else if (auto *Ref = dyn_cast<StructuredGEPInst>(I)) {
1415 if (GR->findDeducedElementType(Ref->getPointerOperand()))
1416 return;
1417 KnownElemTy = Ref->getBaseType();
1418 Ops.push_back(std::make_pair(Ref->getPointerOperand(),
1420 } else if (auto *Ref = dyn_cast<LoadInst>(I)) {
1421 KnownElemTy = I->getType();
1422 if (isUntypedPointerTy(KnownElemTy)) {
1423 // A T** loaded back from its alloca comes out opaque, dropping type info.
1424 // When the load is a pointer-to-pointer, type the alloca as that pointer.
1425 Type *LoadedElemTy = GR->findDeducedElementType(I);
1426 if (!LoadedElemTy || !isPointerTyOrWrapper(LoadedElemTy))
1427 return;
1428 Value *Root = Ref->getPointerOperand()->stripPointerCasts();
1429 if (!isa<AllocaInst>(Root))
1430 return;
1431 KnownElemTy = getTypedPointerWrapper(LoadedElemTy,
1432 getPointerAddressSpace(KnownElemTy));
1433 }
1434 Type *PointeeTy = GR->findDeducedElementType(Ref->getPointerOperand());
1435 if (PointeeTy && !isUntypedPointerTy(PointeeTy))
1436 return;
1437 Ops.push_back(std::make_pair(Ref->getPointerOperand(),
1439 } else if (auto *Ref = dyn_cast<StoreInst>(I)) {
1440 if (!(KnownElemTy =
1441 reconstructType(Ref->getValueOperand(), false, IsPostprocessing)))
1442 return;
1443 Type *PointeeTy = GR->findDeducedElementType(Ref->getPointerOperand());
1444 if (PointeeTy && !isUntypedPointerTy(PointeeTy))
1445 return;
1446 Ops.push_back(std::make_pair(Ref->getPointerOperand(),
1448 } else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) {
1449 KnownElemTy = isPointerTy(I->getType())
1450 ? getAtomicElemTy(GR, I, Ref->getPointerOperand())
1451 : I->getType();
1452 if (!KnownElemTy)
1453 return;
1454 Incomplete = isTodoType(Ref->getPointerOperand());
1455 Ops.push_back(std::make_pair(Ref->getPointerOperand(),
1457 } else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) {
1458 KnownElemTy = isPointerTy(I->getType())
1459 ? getAtomicElemTy(GR, I, Ref->getPointerOperand())
1460 : I->getType();
1461 if (!KnownElemTy)
1462 return;
1463 Incomplete = isTodoType(Ref->getPointerOperand());
1464 Ops.push_back(std::make_pair(Ref->getPointerOperand(),
1466 } else if (auto *Ref = dyn_cast<SelectInst>(I)) {
1467 if (!isPointerTy(I->getType()) ||
1468 !(KnownElemTy = GR->findDeducedElementType(I)))
1469 return;
1470 Incomplete = isTodoType(I);
1471 for (unsigned i = 0; i < Ref->getNumOperands(); i++) {
1472 Value *Op = Ref->getOperand(i);
1473 if (isPointerTy(Op->getType()))
1474 Ops.push_back(std::make_pair(Op, i));
1475 }
1476 } else if (auto *Ref = dyn_cast<ReturnInst>(I)) {
1477 if (!isPointerTy(CurrF->getReturnType()))
1478 return;
1479 Value *Op = Ref->getReturnValue();
1480 if (!Op)
1481 return;
1482 if (deduceOperandElementTypeFunctionRet(I, IncompleteRets, AskOps,
1483 IsPostprocessing, KnownElemTy, Op,
1484 CurrF))
1485 return;
1486 Incomplete = isTodoType(CurrF);
1487 Ops.push_back(std::make_pair(Op, 0));
1488 } else if (auto *Ref = dyn_cast<ICmpInst>(I)) {
1489 if (!isPointerTy(Ref->getOperand(0)->getType()))
1490 return;
1491 Value *Op0 = Ref->getOperand(0);
1492 Value *Op1 = Ref->getOperand(1);
1493 bool Incomplete0 = isTodoType(Op0);
1494 bool Incomplete1 = isTodoType(Op1);
1495 Type *ElemTy1 = GR->findDeducedElementType(Op1);
1496 Type *ElemTy0 = (Incomplete0 && !Incomplete1 && ElemTy1)
1497 ? nullptr
1498 : GR->findDeducedElementType(Op0);
1499 if (ElemTy0) {
1500 KnownElemTy = ElemTy0;
1501 Incomplete = Incomplete0;
1502 Ops.push_back(std::make_pair(Op1, 1));
1503 } else if (ElemTy1) {
1504 KnownElemTy = ElemTy1;
1505 Incomplete = Incomplete1;
1506 Ops.push_back(std::make_pair(Op0, 0));
1507 }
1508 } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
1509 if (!CI->isIndirectCall())
1510 deduceOperandElementTypeCalledFunction(CI, Ops, KnownElemTy, Incomplete);
1511 else if (HaveFunPtrs)
1512 deduceOperandElementTypeFunctionPointer(CI, Ops, KnownElemTy,
1513 IsPostprocessing);
1514 }
1515
1516 // There is no enough info to deduce types or all is valid.
1517 if (!KnownElemTy || Ops.size() == 0)
1518 return;
1519
1520 LLVMContext &Ctx = CurrF->getContext();
1521 IRBuilder<> B(Ctx);
1522 for (auto &OpIt : Ops) {
1523 Value *Op = OpIt.first;
1524 if (AskOps && !AskOps->contains(Op))
1525 continue;
1526 Type *AskTy = nullptr;
1527 CallInst *AskCI = nullptr;
1528 if (IsPostprocessing && AskOps) {
1529 AskTy = GR->findDeducedElementType(Op);
1530 AskCI = GR->findAssignPtrTypeInstr(Op);
1531 assert(AskTy && AskCI);
1532 }
1533 Type *Ty = AskTy ? AskTy : GR->findDeducedElementType(Op);
1534 if (Ty == KnownElemTy)
1535 continue;
1536 Value *OpTyVal = getNormalizedPoisonValue(KnownElemTy);
1537 Type *OpTy = Op->getType();
1538 // Do not let a non-pointer element type clobber an already-deduced pointer
1539 // pointee.
1540 bool WouldClobberPtrWithNonPtr = Ty && isPointerTyOrWrapper(Ty) &&
1541 !isPointerTyOrWrapper(KnownElemTy) &&
1543 if (Op->hasUseList() && !WouldClobberPtrWithNonPtr &&
1544 (!Ty || AskTy || isUntypedPointerTy(Ty) || isTodoType(Op))) {
1545 Type *PrevElemTy = GR->findDeducedElementType(Op);
1546 GR->addDeducedElementType(Op, normalizeType(KnownElemTy));
1547 // check if KnownElemTy is complete
1548 if (!Incomplete)
1549 eraseTodoType(Op);
1550 else if (!IsPostprocessing)
1551 insertTodoType(Op);
1552 // check if there is existing Intrinsic::spv_assign_ptr_type instruction
1553 CallInst *AssignCI = AskCI ? AskCI : GR->findAssignPtrTypeInstr(Op);
1554 if (AssignCI == nullptr) {
1555 Instruction *User = dyn_cast<Instruction>(Op->use_begin()->get());
1556 setInsertPointSkippingPhis(B, User ? User->getNextNode() : I);
1557 CallInst *CI =
1558 buildIntrWithMD(Intrinsic::spv_assign_ptr_type, {OpTy}, OpTyVal, Op,
1559 {B.getInt32(getPointerAddressSpace(OpTy))}, B);
1560 GR->addAssignPtrTypeInstr(Op, CI);
1561 } else {
1562 GR->updateAssignType(AssignCI, Op, OpTyVal);
1563 DenseSet<std::pair<Value *, Value *>> VisitedSubst{
1564 std::make_pair(I, Op)};
1565 propagateElemTypeRec(Op, KnownElemTy, PrevElemTy, VisitedSubst);
1566 }
1567 } else {
1568 eraseTodoType(Op);
1569 CallInst *PtrCastI =
1570 buildSpvPtrcast(I->getParent()->getParent(), Op, KnownElemTy);
1571 if (OpIt.second == std::numeric_limits<unsigned>::max())
1572 dyn_cast<CallInst>(I)->setCalledOperand(PtrCastI);
1573 else
1574 I->setOperand(OpIt.second, PtrCastI);
1575 }
1576 }
1577 TypeValidated.insert(I);
1578}
1579
1580void SPIRVEmitIntrinsics::replaceMemInstrUses(Instruction *Old,
1581 Instruction *New,
1582 IRBuilder<> &B) {
1583 while (!Old->user_empty()) {
1584 auto *U = Old->user_back();
1585 if (isAssignTypeInstr(U)) {
1586 B.SetInsertPoint(U);
1587 SmallVector<Value *, 2> Args = {New, U->getOperand(1)};
1588 CallInst *AssignCI = B.CreateIntrinsicWithoutFolding(
1589 Intrinsic::spv_assign_type, {New->getType()}, Args);
1590 GR->addAssignPtrTypeInstr(New, AssignCI);
1591 U->eraseFromParent();
1592 } else if (isMemInstrToReplace(U) || isa<ReturnInst>(U) ||
1593 isa<CallInst>(U)) {
1594 U->replaceUsesOfWith(Old, New);
1595 // For a `llvm.spv.abort` call whose composite message argument was
1596 // rewritten to a value-id (i32), also retarget the call to a matching
1597 // intrinsic declaration so the IR verifier is satisfied. The SPIR-V
1598 // type of the value is tracked via the GlobalRegistry, so the selector
1599 // still emits OpAbortKHR with the original composite type.
1600 if (auto *CI = dyn_cast<CallInst>(U);
1601 CI && CI->getIntrinsicID() == Intrinsic::spv_abort) {
1602 Type *NewArgTy = New->getType();
1603 Type *ExpectedArgTy = CI->getFunctionType()->getParamType(0);
1604 if (NewArgTy != ExpectedArgTy) {
1605 Module *M = CI->getModule();
1607 M, Intrinsic::spv_abort, {NewArgTy});
1608 CI->setCalledFunction(NewF);
1609 }
1610 }
1611 } else if (isa<PHINode>(U) || isa<SelectInst>(U) || isa<FreezeInst>(U)) {
1612 // Aggregate-typed PHIs, selects and freezes have already been mutated to
1613 // the i32 value-id type up front in runOnFunction, so only the operand
1614 // needs replacing here; their extractvalue users are lowered to
1615 // spv_extractv by visitExtractValueInst.
1616 assert(U->getType() == New->getType() &&
1617 "aggregate PHI/select/freeze should have been mutated to value-id "
1618 "type");
1619 U->replaceUsesOfWith(Old, New);
1620 } else {
1621 llvm_unreachable("illegal aggregate intrinsic user");
1622 }
1623 }
1624 New->copyMetadata(*Old);
1625 Old->eraseFromParent();
1626}
1627
1628// Lower a poison or undef Op to its placeholder intrinsic.
1629Value *SPIRVEmitIntrinsics::lowerUndefOrPoison(Value *Op, IRBuilder<> &B,
1630 bool HasPoisonExt) {
1631 auto *UV = dyn_cast<UndefValue>(Op);
1632 if (!UV)
1633 return nullptr;
1634
1635 bool AsPoison = HasPoisonExt && isa<PoisonValue>(UV);
1636 if (isa<PoisonValue>(UV) && !HasPoisonExt)
1637 LLVM_DEBUG(dbgs() << "SPV_KHR_poison_freeze is not enabled. Poison is "
1638 "lowered as undef\n");
1639
1640 Intrinsic::ID IID = AsPoison ? Intrinsic::spv_poison : Intrinsic::spv_undef;
1641 Type *Ty = UV->getType();
1642
1643 // Aggregates use an i32-result placeholder with the real type kept in
1644 // AggrConstTypes and scalar poison uses a type-overloaded one.
1645 if (Ty->isAggregateType()) {
1646 auto *Call =
1647 AsPoison ? B.CreateIntrinsicWithoutFolding(IID, {B.getInt32Ty()}, {})
1648 : B.CreateIntrinsicWithoutFolding(IID, {});
1649 AggrConsts[Call] = UV;
1650 AggrConstTypes[Call] = Ty;
1651 return Call;
1652 }
1653
1654 if (AsPoison)
1655 return B.CreateIntrinsic(IID, {Ty}, {});
1656 return nullptr;
1657}
1658
1659// Replace aggregate undef or poison operands and extension-enabled scalar
1660// poison operands with placeholder intrinsics. Scalar undef is left as is. See
1661// lowerUndefOrPoison.
1662void SPIRVEmitIntrinsics::preprocessUndefsAndPoisons(IRBuilder<> &B) {
1663 const SPIRVSubtarget *STI = TM.getSubtargetImpl(*CurrF);
1664 bool HasPoisonExt =
1665 STI->canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
1666
1667 SmallVector<Instruction *, 16> Insts;
1668 for (auto &I : instructions(CurrF))
1669 Insts.push_back(&I);
1670
1671 for (Instruction *I : Insts) {
1672 bool BPrepared = false;
1673 auto *Phi = dyn_cast<PHINode>(I);
1674 for (unsigned Idx = 0; Idx < I->getNumOperands(); ++Idx) {
1675 Value *Op = I->getOperand(Idx);
1676 if (!isa<UndefValue>(Op) || Op->getType()->isMetadataTy())
1677 continue;
1678 bool IsScalar = !Op->getType()->isAggregateType();
1679 bool AsPoison = HasPoisonExt && isa<PoisonValue>(Op);
1680 // Scalar undef or extensionless scalar poison is directly translatable.
1681 if (IsScalar && !AsPoison)
1682 continue;
1683 // Scalar poison in a phi materializes in the incoming block. Everything
1684 // else materializes right before I.
1685 if (IsScalar && Phi)
1686 B.SetInsertPoint(Phi->getIncomingBlock(Idx)->getTerminator());
1687 else if (!BPrepared) {
1689 BPrepared = true;
1690 }
1691 if (Value *Repl = lowerUndefOrPoison(Op, B, HasPoisonExt))
1692 I->setOperand(Idx, Repl);
1693 }
1694 }
1695}
1696
1697// Simplify addrspacecast(null) instructions to ConstantPointerNull of the
1698// target type. Casting null always yields null, and this avoids SPIR-V
1699// lowering issues where the null gets typed as an integer instead of a
1700// pointer.
1701void SPIRVEmitIntrinsics::simplifyNullAddrSpaceCasts() {
1702 for (Instruction &I : make_early_inc_range(instructions(CurrF)))
1703 if (auto *ASC = dyn_cast<AddrSpaceCastInst>(&I))
1704 if (isa<ConstantPointerNull>(ASC->getPointerOperand())) {
1705 ASC->replaceAllUsesWith(
1707 ASC->eraseFromParent();
1708 }
1709}
1710
1711// True for an aggregate value the legalizer splits into a multi-result op
1712// (with.overflow -> G_UADDO, frexp/sincos/modf -> G_FFREXP/...). These keep a
1713// genuine multi-register result; all other aggregates become a single value-id.
1715 if (!V->getType()->isAggregateType())
1716 return false;
1717 return isa<IntrinsicInst>(V) && !isSpvIntrinsic(V);
1718}
1719
1720// True for an aggregate PHI/select/freeze, which is lowered to a single
1721// value-id.
1723 return (isa<PHINode>(I) || isa<SelectInst>(I) || isa<FreezeInst>(I)) &&
1724 I.getType()->isAggregateType();
1725}
1726
1727// Give each multi-register aggregate arm of an aggregate PHI/select/freeze a
1728// single value-id by reassembling it with extractvalue + insertvalue, so the
1729// arm matches the result once it is mutated to a value-id.
1730void SPIRVEmitIntrinsics::insertCompositeAggregateArms(Instruction *I,
1731 IRBuilder<> &B) {
1732 auto *Phi = dyn_cast<PHINode>(I);
1733 for (Use &U : I->operands()) {
1734 Value *Op = U.get();
1736 continue;
1737 // A PHI arm materializes in its incoming block, everything else after the
1738 // producer.
1739 if (Phi)
1740 B.SetInsertPoint(Phi->getIncomingBlock(U)->getTerminator());
1741 else
1743 auto *AggrTy = cast<StructType>(Op->getType());
1744 Value *Composite = PoisonValue::get(AggrTy);
1745 for (unsigned Idx = 0, E = AggrTy->getNumElements(); Idx != E; ++Idx) {
1746 Value *Field = B.CreateExtractValue(Op, Idx);
1747 Composite = B.CreateInsertValue(Composite, Field, Idx);
1748 }
1749 U.set(Composite);
1750 }
1751}
1752
1753void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) {
1754 const SPIRVSubtarget *STI = TM.getSubtargetImpl(*CurrF);
1755 bool HasPoisonExt =
1756 STI->canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
1757 std::queue<Instruction *> Worklist;
1758 for (auto &I : instructions(CurrF))
1759 Worklist.push(&I);
1760
1761 while (!Worklist.empty()) {
1762 auto *I = Worklist.front();
1763 bool IsPhi = isa<PHINode>(I), BPrepared = false;
1764 assert(I);
1765 bool KeepInst = false;
1766 for (const auto &Op : I->operands()) {
1767 Constant *AggrConst = nullptr;
1768 Type *ResTy = nullptr;
1769 if (auto *COp = dyn_cast<ConstantVector>(Op)) {
1770 AggrConst = COp;
1771 ResTy = COp->getType();
1772 } else if (auto *COp = dyn_cast<ConstantArray>(Op)) {
1773 AggrConst = COp;
1774 ResTy = B.getInt32Ty();
1775 } else if (auto *COp = dyn_cast<ConstantStruct>(Op)) {
1776 AggrConst = COp;
1777 ResTy = B.getInt32Ty();
1778 } else if (auto *COp = dyn_cast<ConstantDataArray>(Op)) {
1779 AggrConst = COp;
1780 ResTy = B.getInt32Ty();
1781 } else if (auto *COp = dyn_cast<ConstantAggregateZero>(Op)) {
1782 AggrConst = COp;
1783 ResTy = Op->getType()->isVectorTy() ? COp->getType() : B.getInt32Ty();
1784 }
1785 if (AggrConst) {
1786 auto PrepareInsert = [&]() {
1787 if (BPrepared)
1788 return;
1789 IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
1790 : B.SetInsertPoint(I);
1791 BPrepared = true;
1792 };
1794 if (auto *COp = dyn_cast<ConstantDataSequential>(Op))
1795 for (unsigned i = 0; i < COp->getNumElements(); ++i)
1796 Args.push_back(COp->getElementAsConstant(i));
1797 else
1798 for (Value *Op : AggrConst->operands()) {
1799 // Simplify addrspacecast(null) to null in the target address space
1800 // so that null pointers get the correct pointer type when lowered.
1801 if (auto *CE = dyn_cast<ConstantExpr>(Op);
1802 CE && CE->getOpcode() == Instruction::AddrSpaceCast &&
1803 isa<ConstantPointerNull>(CE->getOperand(0)))
1805 // Undef or poison nested in a constant aggregate is not a direct
1806 // instruction operand, so preprocessUndefsAndPoisons() misses it.
1807 // An unlowered aggregate one would reach IRTranslator as an
1808 // untranslatable spv_const_composite operand.
1809 if (isa<UndefValue>(Op)) {
1810 PrepareInsert();
1811 if (Value *Repl = lowerUndefOrPoison(Op, B, HasPoisonExt))
1812 Op = Repl;
1813 }
1814 Args.push_back(Op);
1815 }
1816 PrepareInsert();
1817 auto *CI = B.CreateIntrinsicWithoutFolding(
1818 Intrinsic::spv_const_composite, {ResTy}, {Args});
1819 Worklist.push(CI);
1820 I->replaceUsesOfWith(Op, CI);
1821 KeepInst = true;
1822 AggrConsts[CI] = AggrConst;
1823 AggrConstTypes[CI] = deduceNestedTypeHelper(AggrConst, false);
1824 }
1825 }
1826 if (!KeepInst)
1827 Worklist.pop();
1828 }
1829}
1830
1832 IRBuilder<> &B) {
1833 LLVMContext &Ctx = I->getContext();
1835 B.CreateIntrinsic(Intrinsic::spv_assign_decoration, {I->getType()},
1836 {I, MetadataAsValue::get(Ctx, MDNode::get(Ctx, {Node}))});
1837}
1838
1840 unsigned RoundingModeDeco,
1841 IRBuilder<> &B) {
1842 LLVMContext &Ctx = I->getContext();
1843 Type *Int32Ty = Type::getInt32Ty(Ctx);
1844 MDNode *RoundingModeNode = MDNode::get(
1845 Ctx,
1847 ConstantInt::get(Int32Ty, SPIRV::Decoration::FPRoundingMode)),
1848 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, RoundingModeDeco))});
1849 createDecorationIntrinsic(I, RoundingModeNode, B);
1850}
1851
1853 IRBuilder<> &B) {
1854 LLVMContext &Ctx = I->getContext();
1855 Type *Int32Ty = Type::getInt32Ty(Ctx);
1856 MDNode *SaturatedConversionNode =
1857 MDNode::get(Ctx, {ConstantAsMetadata::get(ConstantInt::get(
1858 Int32Ty, SPIRV::Decoration::SaturatedConversion))});
1859 createDecorationIntrinsic(I, SaturatedConversionNode, B);
1860}
1861
1866
1867Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
1868 if (!Call.isInlineAsm())
1869 return &Call;
1870
1871 LLVMContext &Ctx = CurrF->getContext();
1872 // TODO: this does not retain elementtype info for memory constraints, which
1873 // in turn means that we lower them into pointers to i8, rather than
1874 // pointers to elementtype; this can be fixed during reverse translation
1875 // but we should correct it here, possibly by tweaking the function
1876 // type to take TypedPointerType args.
1877 Constant *TyC = UndefValue::get(SPIRV::getOriginalFunctionType(Call));
1878 MDString *ConstraintString =
1879 MDString::get(Ctx, SPIRV::getOriginalAsmConstraints(Call));
1881 buildMD(TyC),
1882 MetadataAsValue::get(Ctx, MDNode::get(Ctx, ConstraintString))};
1883 for (unsigned OpIdx = 0; OpIdx < Call.arg_size(); OpIdx++)
1884 Args.push_back(Call.getArgOperand(OpIdx));
1885
1887 B.SetInsertPoint(&Call);
1888 B.CreateIntrinsic(Intrinsic::spv_inline_asm, {Args});
1889 return &Call;
1890}
1891
1892// Use a tip about rounding mode to create a decoration.
1893void SPIRVEmitIntrinsics::useRoundingMode(ConstrainedFPIntrinsic *FPI,
1894 IRBuilder<> &B) {
1895 std::optional<RoundingMode> RM = FPI->getRoundingMode();
1896 if (!RM.has_value())
1897 return;
1898 unsigned RoundingModeDeco = std::numeric_limits<unsigned>::max();
1899 switch (RM.value()) {
1900 default:
1901 // ignore unknown rounding modes
1902 break;
1903 case RoundingMode::NearestTiesToEven:
1904 RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTE;
1905 break;
1906 case RoundingMode::TowardNegative:
1907 RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTN;
1908 break;
1909 case RoundingMode::TowardPositive:
1910 RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTP;
1911 break;
1912 case RoundingMode::TowardZero:
1913 RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTZ;
1914 break;
1915 case RoundingMode::Dynamic:
1916 case RoundingMode::NearestTiesToAway:
1917 // TODO: check if supported
1918 break;
1919 }
1920 if (RoundingModeDeco == std::numeric_limits<unsigned>::max())
1921 return;
1922 // Convert the tip about rounding mode into a decoration record.
1923 createRoundingModeDecoration(FPI, RoundingModeDeco, B);
1924}
1925
1926Instruction *SPIRVEmitIntrinsics::visitSwitchInst(SwitchInst &I) {
1927 BasicBlock *ParentBB = I.getParent();
1928 Function *F = ParentBB->getParent();
1929 IRBuilder<> B(ParentBB);
1930 B.SetInsertPoint(&I);
1931 SmallVector<Value *, 4> Args;
1933 Args.push_back(I.getCondition());
1934 BBCases.push_back(I.getDefaultDest());
1935 Args.push_back(BlockAddress::get(F, I.getDefaultDest()));
1936 for (auto &Case : I.cases()) {
1937 Args.push_back(Case.getCaseValue());
1938 BBCases.push_back(Case.getCaseSuccessor());
1939 Args.push_back(BlockAddress::get(F, Case.getCaseSuccessor()));
1940 }
1941 CallInst *NewI = B.CreateIntrinsicWithoutFolding(
1942 Intrinsic::spv_switch, {I.getOperand(0)->getType()}, {Args});
1943 // remove switch to avoid its unneeded and undesirable unwrap into branches
1944 // and conditions
1945 replaceAllUsesWith(&I, NewI);
1946 I.eraseFromParent();
1947 // insert artificial and temporary instruction to preserve valid CFG,
1948 // it will be removed after IR translation pass
1949 B.SetInsertPoint(ParentBB);
1950 IndirectBrInst *BrI = B.CreateIndirectBr(
1951 Constant::getNullValue(PointerType::getUnqual(ParentBB->getContext())),
1952 BBCases.size());
1953 for (BasicBlock *BBCase : BBCases)
1954 BrI->addDestination(BBCase);
1955 return BrI;
1956}
1957
1959 return GEP->getNumIndices() > 0 && match(GEP->getOperand(1), m_Zero());
1960}
1961
1962Instruction *SPIRVEmitIntrinsics::visitIntrinsicInst(IntrinsicInst &I) {
1963 auto *SGEP = dyn_cast<StructuredGEPInst>(&I);
1964 if (!SGEP)
1965 return &I;
1966
1967 IRBuilder<> B(I.getParent());
1968 B.SetInsertPoint(&I);
1969 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
1970 SmallVector<Value *, 4> Args;
1971 Args.push_back(/* inBounds= */ B.getInt1(true));
1972 Args.push_back(I.getOperand(0));
1973 Args.push_back(/* zero index */ B.getInt32(0));
1974 for (unsigned J = 0; J < SGEP->getNumIndices(); ++J)
1975 Args.push_back(SGEP->getIndexOperand(J));
1976
1977 Instruction *NewI =
1978 B.CreateIntrinsicWithoutFolding(Intrinsic::spv_gep, Types, Args);
1979 replaceAllUsesWithAndErase(B, &I, NewI);
1980 return NewI;
1981}
1982
1983Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst(GetElementPtrInst &I) {
1984 IRBuilder<> B(I.getParent());
1985 B.SetInsertPoint(&I);
1986
1987 // OpPtrAccessChain requires a scalar pointer result; scalarize per-lane
1988 // GEPs that return <N x ptr> and rebuild the vector via insertelement.
1989 if (auto *RetVTy = dyn_cast<FixedVectorType>(I.getType())) {
1990 unsigned N = RetVTy->getNumElements();
1991 Value *PtrOp = I.getPointerOperand();
1992 bool PtrIsVec = isa<VectorType>(PtrOp->getType());
1993 Type *ResultPtrTy = RetVTy->getElementType();
1994 Type *ScalarPtrTy = PtrOp->getType()->getScalarType();
1995 SmallVector<Type *, 2> GepTypes = {ResultPtrTy, ScalarPtrTy};
1996 Value *InBounds = B.getInt1(I.isInBounds());
1997 Type *LanePointeeTy = getGEPType(&I);
1998 Type *SrcElemTy = I.getSourceElementType();
1999
2000 // Pin the lane pointee type on the vector operand and on each extracted
2001 // lane so the prelegalizer wraps them as OpTypeVector/OpTypePointer of
2002 // the right element type instead of defaulting to i8.
2003 if (PtrIsVec)
2004 GR->buildAssignPtr(B, SrcElemTy, PtrOp);
2005
2006 Value *VecResult = PoisonValue::get(RetVTy);
2007 for (unsigned Lane = 0; Lane < N; ++Lane) {
2008 Value *LaneIdx = B.getInt32(Lane);
2009 Value *ScalarPtr = PtrOp;
2010 if (PtrIsVec) {
2011 SmallVector<Type *, 3> ExtractTypes = {ScalarPtrTy, PtrOp->getType(),
2012 LaneIdx->getType()};
2013 ScalarPtr = B.CreateIntrinsic(Intrinsic::spv_extractelt, {ExtractTypes},
2014 {PtrOp, LaneIdx});
2015 GR->buildAssignPtr(B, SrcElemTy, ScalarPtr);
2016 }
2017 SmallVector<Value *, 4> Args;
2018 Args.push_back(InBounds);
2019 Args.push_back(ScalarPtr);
2020 for (Value *Idx : I.indices()) {
2021 if (isa<VectorType>(Idx->getType()))
2022 Args.push_back(B.CreateExtractElement(Idx, LaneIdx));
2023 else
2024 Args.push_back(Idx);
2025 }
2026 Value *ScalarGep = B.CreateIntrinsic(Intrinsic::spv_gep, GepTypes, Args);
2027 GR->buildAssignPtr(B, LanePointeeTy, ScalarGep);
2028 VecResult = B.CreateInsertElement(VecResult, ScalarGep, LaneIdx);
2029 }
2030
2031 auto *NewI = cast<Instruction>(VecResult);
2032 replaceAllUsesWithAndErase(B, &I, NewI);
2033
2034 if (CallInst *Old = GR->findAssignPtrTypeInstr(NewI)) {
2035 Old->eraseFromParent();
2036 GR->addAssignPtrTypeInstr(NewI, nullptr);
2037 }
2039 GR->buildAssignPtr(B, LanePointeeTy, NewI);
2040
2041 return NewI;
2042 }
2043
2045 // Logical SPIR-V cannot use the OpPtrAccessChain instruction. If the first
2046 // index of the GEP is not 0, then we need to try to adjust it.
2047 //
2048 // If the GEP is doing byte addressing, try to rebuild the full access chain
2049 // from the type of the pointer.
2050 if (getByteAddressingMultiplier(I.getSourceElementType())) {
2051 return buildLogicalAccessChainFromGEP(I);
2052 }
2053
2054 // Look for the array-to-pointer decay. If this is the pattern
2055 // we can adjust the types, and prepend a 0 to the indices.
2056 Value *PtrOp = I.getPointerOperand();
2057 Type *SrcElemTy = I.getSourceElementType();
2058 Type *DeducedPointeeTy = deduceElementType(PtrOp, true);
2059
2060 if (auto *ArrTy = dyn_cast<ArrayType>(DeducedPointeeTy)) {
2061 if (ArrTy->getElementType() == SrcElemTy) {
2062 SmallVector<Value *> NewIndices;
2063 Type *FirstIdxType = I.getOperand(1)->getType();
2064 NewIndices.push_back(ConstantInt::get(FirstIdxType, 0));
2065 for (Value *Idx : I.indices())
2066 NewIndices.push_back(Idx);
2067
2068 SmallVector<Type *, 2> Types = {I.getType(), I.getPointerOperandType()};
2069 SmallVector<Value *, 4> Args;
2070 Args.push_back(B.getInt1(I.isInBounds()));
2071 Args.push_back(I.getPointerOperand());
2072 Args.append(NewIndices.begin(), NewIndices.end());
2073
2074 Instruction *NewI = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_gep,
2075 {Types}, {Args});
2076 replaceAllUsesWithAndErase(B, &I, NewI);
2077 return NewI;
2078 }
2079 }
2080 }
2081
2082 SmallVector<Type *, 2> Types = {I.getType(), I.getOperand(0)->getType()};
2083 SmallVector<Value *, 4> Args;
2084 Args.push_back(B.getInt1(I.isInBounds()));
2085 llvm::append_range(Args, I.operands());
2086 Instruction *NewI =
2087 B.CreateIntrinsicWithoutFolding(Intrinsic::spv_gep, {Types}, {Args});
2088 replaceAllUsesWithAndErase(B, &I, NewI);
2089 return NewI;
2090}
2091
2092Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
2093 IRBuilder<> B(I.getParent());
2094 B.SetInsertPoint(&I);
2095 Value *Source = I.getOperand(0);
2096
2097 // SPIR-V, contrary to LLVM 17+ IR, supports bitcasts between pointers of
2098 // varying element types. In case of IR coming from older versions of LLVM
2099 // such bitcasts do not provide sufficient information, should be just skipped
2100 // here, and handled in insertPtrCastOrAssignTypeInstr.
2101 if (isPointerTy(I.getType())) {
2102 replaceAllUsesWith(&I, Source);
2103 I.eraseFromParent();
2104 return nullptr;
2105 }
2106
2107 SmallVector<Type *, 2> Types = {I.getType(), Source->getType()};
2108 SmallVector<Value *> Args(I.op_begin(), I.op_end());
2109 Instruction *NewI =
2110 B.CreateIntrinsicWithoutFolding(Intrinsic::spv_bitcast, {Types}, {Args});
2111 replaceAllUsesWithAndErase(B, &I, NewI);
2112 return NewI;
2113}
2114
2115void SPIRVEmitIntrinsics::insertAssignPtrTypeTargetExt(
2116 TargetExtType *AssignedType, Value *V, IRBuilder<> &B) {
2117 Type *VTy = V->getType();
2118
2119 // A couple of sanity checks.
2120 assert((isPointerTy(VTy)) && "Expect a pointer type!");
2121 if (Type *ElemTy = getPointeeType(VTy))
2122 if (ElemTy != AssignedType)
2123 report_fatal_error("Unexpected pointer element type!");
2124
2125 CallInst *AssignCI = GR->findAssignPtrTypeInstr(V);
2126 if (!AssignCI) {
2127 GR->buildAssignType(B, AssignedType, V);
2128 return;
2129 }
2130
2131 Type *CurrentType =
2133 cast<MetadataAsValue>(AssignCI->getOperand(1))->getMetadata())
2134 ->getType();
2135 if (CurrentType == AssignedType)
2136 return;
2137
2138 // Builtin types cannot be redeclared or casted.
2139 if (CurrentType->isTargetExtTy())
2140 report_fatal_error("Type mismatch " + CurrentType->getTargetExtName() +
2141 "/" + AssignedType->getTargetExtName() +
2142 " for value " + V->getName(),
2143 false);
2144
2145 // Our previous guess about the type seems to be wrong, let's update
2146 // inferred type according to a new, more precise type information.
2147 GR->updateAssignType(AssignCI, V, getNormalizedPoisonValue(AssignedType));
2148}
2149
2150void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
2151 Instruction *I, Value *Pointer, Type *ExpectedElementType,
2152 unsigned OperandToReplace, IRBuilder<> &B) {
2153 TypeValidated.insert(I);
2154
2155 // Do not emit spv_ptrcast if Pointer's element type is ExpectedElementType
2156 Type *PointerElemTy = deduceElementTypeHelper(Pointer, false);
2157 if (PointerElemTy == ExpectedElementType ||
2158 isEquivalentTypes(PointerElemTy, ExpectedElementType))
2159 return;
2160
2162 Value *ExpectedElementVal = getNormalizedPoisonValue(ExpectedElementType);
2163 MetadataAsValue *VMD = buildMD(ExpectedElementVal);
2164 unsigned AddressSpace = getPointerAddressSpace(Pointer->getType());
2165 bool FirstPtrCastOrAssignPtrType = true;
2166
2167 // Do not emit new spv_ptrcast if equivalent one already exists or when
2168 // spv_assign_ptr_type already targets this pointer with the same element
2169 // type.
2170 if (Pointer->hasUseList()) {
2171 for (auto User : Pointer->users()) {
2172 auto *II = dyn_cast<IntrinsicInst>(User);
2173 if (!II ||
2174 (II->getIntrinsicID() != Intrinsic::spv_assign_ptr_type &&
2175 II->getIntrinsicID() != Intrinsic::spv_ptrcast) ||
2176 II->getOperand(0) != Pointer)
2177 continue;
2178
2179 // There is some spv_ptrcast/spv_assign_ptr_type already targeting this
2180 // pointer.
2181 FirstPtrCastOrAssignPtrType = false;
2182 if (II->getOperand(1) != VMD ||
2183 dyn_cast<ConstantInt>(II->getOperand(2))->getSExtValue() !=
2185 continue;
2186
2187 // The spv_ptrcast/spv_assign_ptr_type targeting this pointer is of the
2188 // same element type and address space.
2189 if (II->getIntrinsicID() != Intrinsic::spv_ptrcast)
2190 return;
2191
2192 // This must be a spv_ptrcast, do not emit new if this one has the same BB
2193 // as I. Otherwise, search for other spv_ptrcast/spv_assign_ptr_type.
2194 if (II->getParent() != I->getParent())
2195 continue;
2196
2197 I->setOperand(OperandToReplace, II);
2198 return;
2199 }
2200 }
2201
2202 // Never replace an already-deduced pointer pointee with a non-pointer one.
2203 // The conflicting use comes from a mis-deduced expected type. Leave the
2204 // operand untouched rather than emitting a ptrcast that re-introduces
2205 // the collapsed type at the use site.
2206 if (PointerElemTy && isPointerTyOrWrapper(PointerElemTy) &&
2207 !isPointerTyOrWrapper(ExpectedElementType) &&
2208 tracesToPointerAlloca(Pointer))
2209 return;
2210
2211 if (isa<Instruction>(Pointer) || isa<Argument>(Pointer)) {
2212 if (FirstPtrCastOrAssignPtrType) {
2213 // If this would be the first spv_ptrcast, do not emit spv_ptrcast and
2214 // emit spv_assign_ptr_type instead.
2215 GR->buildAssignPtr(B, ExpectedElementType, Pointer);
2216 return;
2217 } else if (isTodoType(Pointer)) {
2218 eraseTodoType(Pointer);
2219 if (!isa<CallInst>(Pointer) && !isaGEP(Pointer) &&
2220 !isa<AllocaInst>(Pointer)) {
2221 // If this wouldn't be the first spv_ptrcast but existing type info is
2222 // uncomplete, update spv_assign_ptr_type arguments.
2223 if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(Pointer)) {
2224 Type *PrevElemTy = GR->findDeducedElementType(Pointer);
2225 assert(PrevElemTy);
2226 DenseSet<std::pair<Value *, Value *>> VisitedSubst{
2227 std::make_pair(I, Pointer)};
2228 GR->updateAssignType(AssignCI, Pointer, ExpectedElementVal);
2229 propagateElemType(Pointer, PrevElemTy, VisitedSubst);
2230 } else {
2231 GR->buildAssignPtr(B, ExpectedElementType, Pointer);
2232 }
2233 return;
2234 }
2235 }
2236 }
2237
2238 // Emit spv_ptrcast
2239 SmallVector<Type *, 2> Types = {Pointer->getType(), Pointer->getType()};
2240 SmallVector<Value *, 2> Args = {Pointer, VMD, B.getInt32(AddressSpace)};
2241 auto *PtrCastI = B.CreateIntrinsic(Intrinsic::spv_ptrcast, {Types}, Args);
2242 I->setOperand(OperandToReplace, PtrCastI);
2243 // We need to set up a pointee type for the newly created spv_ptrcast.
2244 GR->buildAssignPtr(B, ExpectedElementType, PtrCastI);
2245}
2246
2247void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
2248 IRBuilder<> &B) {
2249 // Handle basic instructions:
2250 StoreInst *SI = dyn_cast<StoreInst>(I);
2251 if (IsKernelArgInt8(CurrF, SI)) {
2252 replacePointerOperandWithPtrCast(
2253 I, SI->getValueOperand(), IntegerType::getInt8Ty(CurrF->getContext()),
2254 0, B);
2255 }
2256 if (SI) {
2257 Value *Op = SI->getValueOperand();
2258 Value *Pointer = SI->getPointerOperand();
2259 Type *OpTy = Op->getType();
2260 if (auto *OpI = dyn_cast<Instruction>(Op)) {
2261 OpTy = restoreMutatedType(GR, OpI, OpTy);
2262 if (auto It = AggrConstTypes.find(OpI); It != AggrConstTypes.end())
2263 OpTy = It->second;
2264 }
2265 if (OpTy == Op->getType())
2266 OpTy = deduceElementTypeByValueDeep(OpTy, Op, false);
2267 replacePointerOperandWithPtrCast(I, Pointer, OpTy, 1, B);
2268 return;
2269 }
2270 if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
2271 Value *Pointer = LI->getPointerOperand();
2272 Type *OpTy = LI->getType();
2273 if (auto *PtrTy = dyn_cast<PointerType>(OpTy)) {
2274 if (Type *ElemTy = GR->findDeducedElementType(LI)) {
2275 OpTy = getTypedPointerWrapper(ElemTy, PtrTy->getAddressSpace());
2276 } else {
2277 Type *NewOpTy = OpTy;
2278 OpTy = deduceElementTypeByValueDeep(OpTy, LI, false);
2279 if (OpTy == NewOpTy)
2280 insertTodoType(Pointer);
2281 }
2282 }
2283 replacePointerOperandWithPtrCast(I, Pointer, OpTy, 0, B);
2284 return;
2285 }
2286 if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
2287 Value *Pointer = GEPI->getPointerOperand();
2288 Type *OpTy = nullptr;
2289
2290 // Logical SPIR-V is not allowed to use Op*PtrAccessChain instructions. If
2291 // the first index is 0, then we can trivially lower to OpAccessChain. If
2292 // not we need to try to rewrite the GEP. We avoid adding a pointer cast at
2293 // this time, and will rewrite the GEP when visiting it.
2294 if (TM.getSubtargetImpl()->isLogicalSPIRV() && !isFirstIndexZero(GEPI)) {
2295 return;
2296 }
2297
2298 // In all cases, fall back to the GEP type if type scavenging failed.
2299 if (!OpTy)
2300 OpTy = GEPI->getSourceElementType();
2301
2302 replacePointerOperandWithPtrCast(I, Pointer, OpTy, 0, B);
2303 if (isNestedPointer(OpTy))
2304 insertTodoType(Pointer);
2305 return;
2306 }
2307
2308 // TODO: review and merge with existing logics:
2309 // Handle calls to builtins (non-intrinsics):
2310 CallInst *CI = dyn_cast<CallInst>(I);
2311 if (!CI || CI->isIndirectCall() || CI->isInlineAsm() ||
2313 return;
2314
2315 // collect information about formal parameter types
2316 std::string DemangledName =
2318 Function *CalledF = CI->getCalledFunction();
2319 SmallVector<Type *, 4> CalledArgTys;
2320 bool HaveTypes = false;
2321 for (unsigned OpIdx = 0; OpIdx < CalledF->arg_size(); ++OpIdx) {
2322 Argument *CalledArg = CalledF->getArg(OpIdx);
2323 Type *ArgType = CalledArg->getType();
2324 if (!isPointerTy(ArgType)) {
2325 CalledArgTys.push_back(nullptr);
2326 } else if (Type *ArgTypeElem = getPointeeType(ArgType)) {
2327 CalledArgTys.push_back(ArgTypeElem);
2328 HaveTypes = true;
2329 } else {
2330 Type *ElemTy = GR->findDeducedElementType(CalledArg);
2331 if (!ElemTy && hasPointeeTypeAttr(CalledArg))
2332 ElemTy = getPointeeTypeByAttr(CalledArg);
2333 if (!ElemTy) {
2334 ElemTy = getPointeeTypeByCallInst(DemangledName, CalledF, OpIdx);
2335 if (ElemTy) {
2336 GR->addDeducedElementType(CalledArg, normalizeType(ElemTy));
2337 } else {
2338 for (User *U : CalledArg->users()) {
2339 if (Instruction *Inst = dyn_cast<Instruction>(U)) {
2340 if ((ElemTy = deduceElementTypeHelper(Inst, false)) != nullptr)
2341 break;
2342 }
2343 }
2344 }
2345 }
2346 HaveTypes |= ElemTy != nullptr;
2347 CalledArgTys.push_back(ElemTy);
2348 }
2349 }
2350
2351 if (DemangledName.empty() && !HaveTypes)
2352 return;
2353
2354 for (unsigned OpIdx = 0; OpIdx < CI->arg_size(); OpIdx++) {
2355 Value *ArgOperand = CI->getArgOperand(OpIdx);
2356 if (!isPointerTy(ArgOperand->getType()))
2357 continue;
2358
2359 // Constants (nulls/undefs) are handled in insertAssignPtrTypeIntrs()
2360 if (!isa<Instruction>(ArgOperand) && !isa<Argument>(ArgOperand)) {
2361 // However, we may have assumptions about the formal argument's type and
2362 // may have a need to insert a ptr cast for the actual parameter of this
2363 // call.
2364 Argument *CalledArg = CalledF->getArg(OpIdx);
2365 if (!GR->findDeducedElementType(CalledArg))
2366 continue;
2367 }
2368
2369 Type *ExpectedType =
2370 OpIdx < CalledArgTys.size() ? CalledArgTys[OpIdx] : nullptr;
2371 if (!ExpectedType && !DemangledName.empty())
2372 ExpectedType = SPIRV::parseBuiltinCallArgumentBaseType(
2373 DemangledName, OpIdx, I->getContext());
2374 if (!ExpectedType || ExpectedType->isVoidTy())
2375 continue;
2376
2377 if (ExpectedType->isTargetExtTy() &&
2379 insertAssignPtrTypeTargetExt(cast<TargetExtType>(ExpectedType),
2380 ArgOperand, B);
2381 else
2382 replacePointerOperandWithPtrCast(CI, ArgOperand, ExpectedType, OpIdx, B);
2383 }
2384}
2385
2386Instruction *SPIRVEmitIntrinsics::visitInsertElementInst(InsertElementInst &I) {
2387 // If it's a <1 x Type> vector type, don't modify it. It's not a legal vector
2388 // type in LLT and IRTranslator will replace it by the scalar.
2389 if (isVector1(I.getType()))
2390 return &I;
2391
2392 SmallVector<Type *, 4> Types = {I.getType(), I.getOperand(0)->getType(),
2393 I.getOperand(1)->getType(),
2394 I.getOperand(2)->getType()};
2395 IRBuilder<> B(I.getParent());
2396 B.SetInsertPoint(&I);
2397 SmallVector<Value *> Args(I.op_begin(), I.op_end());
2398 Instruction *NewI = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_insertelt,
2399 {Types}, {Args});
2400 replaceAllUsesWithAndErase(B, &I, NewI);
2401 return NewI;
2402}
2403
2405SPIRVEmitIntrinsics::visitExtractElementInst(ExtractElementInst &I) {
2406 // If it's a <1 x Type> vector type, don't modify it. It's not a legal vector
2407 // type in LLT and IRTranslator will replace it by the scalar.
2408 if (isVector1(I.getVectorOperandType()))
2409 return &I;
2410
2411 IRBuilder<> B(I.getParent());
2412 B.SetInsertPoint(&I);
2413 SmallVector<Type *, 3> Types = {I.getType(), I.getVectorOperandType(),
2414 I.getIndexOperand()->getType()};
2415 SmallVector<Value *, 2> Args = {I.getVectorOperand(), I.getIndexOperand()};
2416 Instruction *NewI = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_extractelt,
2417 {Types}, {Args});
2418 replaceAllUsesWithAndErase(B, &I, NewI);
2419 return NewI;
2420}
2421
2422Instruction *SPIRVEmitIntrinsics::visitInsertValueInst(InsertValueInst &I) {
2423 IRBuilder<> B(I.getParent());
2424 B.SetInsertPoint(&I);
2425 SmallVector<Type *, 1> Types = {I.getInsertedValueOperand()->getType()};
2427 Value *AggregateOp = I.getAggregateOperand();
2428 if (isa<UndefValue>(AggregateOp))
2429 Args.push_back(UndefValue::get(B.getInt32Ty()));
2430 else
2431 Args.push_back(AggregateOp);
2432 Args.push_back(I.getInsertedValueOperand());
2433 for (auto &Op : I.indices())
2434 Args.push_back(B.getInt32(Op));
2435 Instruction *NewI =
2436 B.CreateIntrinsicWithoutFolding(Intrinsic::spv_insertv, {Types}, {Args});
2437 replaceMemInstrUses(&I, NewI, B);
2438 return NewI;
2439}
2440
2441Instruction *SPIRVEmitIntrinsics::visitExtractValueInst(ExtractValueInst &I) {
2442 IRBuilder<> B(I.getParent());
2443 B.SetInsertPoint(&I);
2444 if (I.getAggregateOperand()->getType()->isAggregateType()) {
2445 // Mutate an aggregate-returning spv_extractv producer to i32 so
2446 // IRTranslator does not see a multi-register value.
2447 CallBase *CB = dyn_cast<CallBase>(I.getAggregateOperand());
2448 if (!CB || CB->getIntrinsicID() != Intrinsic::spv_extractv)
2449 return &I;
2450 CB->mutateType(B.getInt32Ty());
2451 }
2452 SmallVector<Value *> Args(I.operands());
2453 for (auto &Op : I.indices())
2454 Args.push_back(B.getInt32(Op));
2455 Instruction *NewI = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_extractv,
2456 {I.getType()}, {Args});
2457 replaceAllUsesWithAndErase(B, &I, NewI);
2458 // If the aggregate result feeds a callsite whose aggregate params were
2459 // rewritten to i32 value-ids by SPIRVPrepareFunctions, mutate it to match.
2460 if (NewI->getType()->isAggregateType()) {
2461 for (const Use &U : NewI->uses()) {
2462 auto *CB = dyn_cast<CallBase>(U.getUser());
2463 if (!CB || !CB->isArgOperand(&U))
2464 continue;
2465 unsigned ArgNo = CB->getArgOperandNo(&U);
2466 FunctionType *FT = CB->getFunctionType();
2467 if (ArgNo < FT->getNumParams() &&
2468 !FT->getParamType(ArgNo)->isAggregateType()) {
2469 NewI->mutateType(B.getInt32Ty());
2470 break;
2471 }
2472 }
2473 }
2474 return NewI;
2475}
2476
2477Instruction *SPIRVEmitIntrinsics::visitLoadInst(LoadInst &I) {
2478 if (!I.getType()->isAggregateType())
2479 return &I;
2480 IRBuilder<> B(I.getParent());
2481 B.SetInsertPoint(&I);
2482 TrackConstants = false;
2483 const auto *TLI = TM.getSubtargetImpl()->getTargetLowering();
2485 TLI->getLoadMemOperandFlags(I, CurrF->getDataLayout());
2486
2487 unsigned IntrinsicId;
2488 SmallVector<Value *, 4> Args = {I.getPointerOperand(), B.getInt16(Flags)};
2489 if (!I.isAtomic()) {
2490 IntrinsicId = Intrinsic::spv_load;
2491 Args.push_back(B.getInt32(I.getAlign().value()));
2492 } else {
2493 IntrinsicId = Intrinsic::spv_atomic_load;
2494 Args.push_back(B.getInt8(static_cast<uint8_t>(I.getOrdering())));
2495 }
2496 CallInst *NewI = B.CreateIntrinsicWithoutFolding(
2497 IntrinsicId, {I.getOperand(0)->getType()}, Args);
2498
2499 replaceMemInstrUses(&I, NewI, B);
2500 return NewI;
2501}
2502
2503Instruction *SPIRVEmitIntrinsics::visitStoreInst(StoreInst &I) {
2504 if (!AggrStores.contains(&I))
2505 return &I;
2506 IRBuilder<> B(I.getParent());
2507 B.SetInsertPoint(&I);
2508 TrackConstants = false;
2509 const auto *TLI = TM.getSubtargetImpl()->getTargetLowering();
2511 TLI->getStoreMemOperandFlags(I, CurrF->getDataLayout());
2512 auto *PtrOp = I.getPointerOperand();
2513
2514 if (I.getValueOperand()->getType()->isAggregateType()) {
2515 // It is possible that what used to be an ExtractValueInst has been replaced
2516 // with a call to the spv_extractv intrinsic, and that said call hasn't
2517 // had its return type replaced with i32 during the dedicated pass (because
2518 // it was emitted later); we have to handle this here, because IRTranslator
2519 // cannot deal with multi-register types at the moment.
2520 CallBase *CB = dyn_cast<CallBase>(I.getValueOperand());
2521 assert(CB && CB->getIntrinsicID() == Intrinsic::spv_extractv &&
2522 "Unexpected argument of aggregate type, should be spv_extractv!");
2523 CB->mutateType(B.getInt32Ty());
2524 }
2525
2526 unsigned IntrinsicId;
2527 SmallVector<Value *, 4> Args = {I.getValueOperand(), PtrOp,
2528 B.getInt16(Flags)};
2529 if (!I.isAtomic()) {
2530 IntrinsicId = Intrinsic::spv_store;
2531 Args.push_back(B.getInt32(I.getAlign().value()));
2532 } else {
2533 IntrinsicId = Intrinsic::spv_atomic_store;
2534 Args.push_back(B.getInt8(static_cast<uint8_t>(I.getOrdering())));
2535 }
2536 Instruction *NewI = B.CreateIntrinsicWithoutFolding(
2537 IntrinsicId, {I.getValueOperand()->getType(), PtrOp->getType()}, Args);
2538 NewI->copyMetadata(I);
2539 I.eraseFromParent();
2540 return NewI;
2541}
2542
2543Instruction *SPIRVEmitIntrinsics::visitAllocaInst(AllocaInst &I) {
2544 Value *ArraySize = nullptr;
2545 if (I.isArrayAllocation()) {
2546 const SPIRVSubtarget *STI = TM.getSubtargetImpl(*I.getFunction());
2547 if (!STI->canUseExtension(
2548 SPIRV::Extension::SPV_INTEL_variable_length_array))
2550 "array allocation: this instruction requires the following "
2551 "SPIR-V extension: SPV_INTEL_variable_length_array",
2552 false);
2553 ArraySize = I.getArraySize();
2554 }
2555 IRBuilder<> B(I.getParent());
2556 B.SetInsertPoint(&I);
2557 TrackConstants = false;
2558 Type *PtrTy = I.getType();
2559 Instruction *NewI =
2560 ArraySize
2561 ? B.CreateIntrinsicWithoutFolding(
2562 Intrinsic::spv_alloca_array, {PtrTy, ArraySize->getType()},
2563 {ArraySize, B.getInt32(I.getAlign().value())})
2564 : B.CreateIntrinsicWithoutFolding(Intrinsic::spv_alloca, {PtrTy},
2565 {B.getInt32(I.getAlign().value())});
2566 replaceAllUsesWithAndErase(B, &I, NewI);
2567 return NewI;
2568}
2569
2570Instruction *SPIRVEmitIntrinsics::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
2571 assert(I.getType()->isAggregateType() && "Aggregate result is expected");
2572 IRBuilder<> B(I.getParent());
2573 B.SetInsertPoint(&I);
2574 SmallVector<Value *> Args(I.operands());
2575 Args.push_back(B.getInt32(
2576 static_cast<uint32_t>(getMemScope(I.getContext(), I.getSyncScopeID()))));
2577 // Per SPIR-V spec atomic ops must combine the ordering bits with the
2578 // storage-class bit.
2579 const SPIRVSubtarget &ST = TM.getSubtarget<SPIRVSubtarget>(*I.getFunction());
2580 unsigned AS = I.getPointerOperand()->getType()->getPointerAddressSpace();
2581 uint32_t ScSem = static_cast<uint32_t>(
2583 Args.push_back(B.getInt32(
2584 static_cast<uint32_t>(getMemSemantics(I.getSuccessOrdering())) | ScSem));
2585 Args.push_back(B.getInt32(
2586 static_cast<uint32_t>(getMemSemantics(I.getFailureOrdering())) | ScSem));
2587 Instruction *NewI = B.CreateIntrinsicWithoutFolding(
2588 Intrinsic::spv_cmpxchg, {I.getPointerOperand()->getType()}, {Args});
2589 replaceMemInstrUses(&I, NewI, B);
2590 return NewI;
2591}
2592
2593static bool isAbortCall(const Instruction &I, const SPIRVSubtarget &ST) {
2594 auto *CI = dyn_cast<CallInst>(&I);
2595 if (!CI)
2596 return false;
2597 switch (CI->getIntrinsicID()) {
2598 case Intrinsic::spv_abort:
2599 return true;
2600 case Intrinsic::trap:
2601 case Intrinsic::ubsantrap:
2602 // When the extension is enabled, selection lowers these to OpAbortKHR.
2603 return ST.canUseExtension(SPIRV::Extension::SPV_KHR_abort);
2604 default:
2605 return false;
2606 }
2607}
2608
2609// The OpAbortKHR instruction itself is a block terminator, so we don't need to
2610// emit an extra OpUnreachable instruction.
2612 const SPIRVSubtarget &ST) {
2613 // Find a previous non-debug instruction.
2614 const Instruction *Prev = I.getPrevNode();
2615 while (Prev && Prev->isDebugOrPseudoInst())
2616 Prev = Prev->getPrevNode();
2617
2618 if (Prev && isAbortCall(*Prev, ST))
2619 return true;
2620
2622 *I.getParent(),
2623 [&ST](const Instruction &II) { return isAbortCall(II, ST); }) &&
2624 "abort-like call must be the last non-debug instruction before its "
2625 "block's terminator");
2626 return false;
2627}
2628
2629Instruction *SPIRVEmitIntrinsics::visitUnreachableInst(UnreachableInst &I) {
2630 const SPIRVSubtarget &ST = TM.getSubtarget<SPIRVSubtarget>(*I.getFunction());
2631 if (precededByAbortIntrinsic(I, ST))
2632 return &I;
2633 IRBuilder<> B(&I);
2634 B.CreateIntrinsic(Intrinsic::spv_unreachable, {});
2635 return &I;
2636}
2637
2638// llvm.compiler.used and llvm.used hold use-list entries that protect their
2639// referenced globals from DCE without participating in code generation.
2640static bool isUseListGlobal(StringRef Name) {
2641 return Name == "llvm.compiler.used" || Name == "llvm.used";
2642}
2643
2644// Returns true for module-level globals that should not have SPIR-V intrinsics
2645// emitted (use-list globals plus llvm.global.annotations).
2647 return isUseListGlobal(Name) || Name == "llvm.global.annotations";
2648}
2649
2650// Returns true if every use of GV traces back to llvm.compiler.used or
2651// llvm.used.
2655 while (!Stack.empty()) {
2656 const Value *V = Stack.pop_back_val();
2657 if (!Visited.insert(V).second)
2658 continue;
2659 if (const auto *GVUser = dyn_cast<GlobalVariable>(V)) {
2660 if (!isUseListGlobal(GVUser->getName()))
2661 return false;
2662 continue;
2663 }
2664 if (const auto *C = dyn_cast<Constant>(V)) {
2665 Stack.append(C->user_begin(), C->user_end());
2666 continue;
2667 }
2668 return false;
2669 }
2670 return true;
2671}
2672
2673static bool
2674shouldEmitIntrinsicsForGlobalValue(const GlobalVariableUsers &GVUsers,
2675 const GlobalVariable &GV,
2676 const Function *F) {
2677 // Skip special artificial variables.
2678 if (isArtificialGlobal(GV.getName()))
2679 return false;
2680
2681 auto &UserFunctions = GVUsers.getTransitiveUserFunctions(GV);
2682 if (UserFunctions.contains(F))
2683 return true;
2684
2685 // Do not emit the intrinsics in this function, it's going to be emitted on
2686 // the functions that reference it.
2687 if (!UserFunctions.empty())
2688 return false;
2689
2690 // Emit definitions for globals that are not referenced by any function on the
2691 // first function definition.
2692 const Module &M = *F->getParent();
2693 const Function &FirstDefinition = *M.getFunctionDefs().begin();
2694 return F == &FirstDefinition;
2695}
2696
2697Value *SPIRVEmitIntrinsics::buildSpvUndefComposite(Type *AggrTy,
2698 IRBuilder<> &B) {
2699 auto MakeLeaf = [&](Type *ElemTy) -> Instruction * {
2700 CallInst *Leaf = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_undef, {});
2701 AggrConsts[Leaf] = PoisonValue::get(ElemTy);
2702 AggrConstTypes[Leaf] = ElemTy;
2703 return Leaf;
2704 };
2705 SmallVector<Value *, 4> Elems;
2706 if (auto *ArrTy = dyn_cast<ArrayType>(AggrTy)) {
2707 Elems.assign(ArrTy->getNumElements(), MakeLeaf(ArrTy->getElementType()));
2708 } else {
2709 auto *StructTy = cast<StructType>(AggrTy);
2710 DenseMap<Type *, Instruction *> LeafByType;
2711 for (unsigned I = 0; I < StructTy->getNumElements(); ++I) {
2712 Type *ElemTy = StructTy->getContainedType(I);
2713 auto &Entry = LeafByType[ElemTy];
2714 if (!Entry)
2715 Entry = MakeLeaf(ElemTy);
2716 Elems.push_back(Entry);
2717 }
2718 }
2719 CallInst *Composite = B.CreateIntrinsicWithoutFolding(
2720 Intrinsic::spv_const_composite, {B.getInt32Ty()}, Elems);
2721 AggrConsts[Composite] = PoisonValue::get(AggrTy);
2722 AggrConstTypes[Composite] = AggrTy;
2723 return Composite;
2724}
2725
2726// If a function directly returns an aggregate-typed call result,
2727// the ReturnInst carries an aggregate while the function signature
2728// was rewritten to i32 by SPIRVPrepareFunctions. Rebuild the return value
2729// via extractvalue/insertvalue so the regular spv_extractv/spv_insertv
2730// lowering produces a valid OpReturnValue.
2731void SPIRVEmitIntrinsics::reconstructAggregateReturns(Function &Func,
2732 IRBuilder<> &B) {
2733 Type *OrigRetTy = GR->findMutated(&Func);
2734 if (!OrigRetTy || !OrigRetTy->isAggregateType())
2735 return;
2736 for (BasicBlock &BB : Func) {
2737 auto *RI = dyn_cast<ReturnInst>(BB.getTerminator());
2738 if (!RI)
2739 continue;
2740 Value *RetVal = RI->getReturnValue();
2741 if (!RetVal || RetVal->getType() != OrigRetTy || !isa<CallBase>(RetVal))
2742 continue;
2743 Type *AggrTy = RetVal->getType();
2744 uint64_t NumElts = isa<StructType>(AggrTy)
2745 ? cast<StructType>(AggrTy)->getNumElements()
2746 : cast<ArrayType>(AggrTy)->getNumElements();
2747 B.SetInsertPoint(RI);
2748 Value *Rebuilt = PoisonValue::get(AggrTy);
2749 for (uint64_t I = 0; I < NumElts; ++I) {
2750 Value *Elt = B.CreateExtractValue(RetVal, I);
2751 Rebuilt = B.CreateInsertValue(Rebuilt, Elt, I);
2752 }
2753 RI->setOperand(0, Rebuilt);
2754 }
2755}
2756
2757void SPIRVEmitIntrinsics::processGlobalValue(GlobalVariable &GV,
2758 IRBuilder<> &B) {
2759
2760 if (!shouldEmitIntrinsicsForGlobalValue(GVUsers, GV, CurrF))
2761 return;
2762
2763 // Record the pointee type for every global, not only initialized ones, so an
2764 // undef non-constant aggregate global is not later collapsed to its element
2765 // type. Result is ignored, because TypedPointerType is not supported
2766 // by llvm IR general logic.
2767 deduceElementTypeHelper(&GV, false);
2768
2769 Constant *Init = nullptr;
2770 if (hasInitializer(&GV)) {
2771 Init = GV.getInitializer();
2772 Value *InitOp = Init;
2773 if (isa<UndefValue>(Init) && Init->getType()->isAggregateType()) {
2774 const SPIRVSubtarget *STI = TM.getSubtargetImpl();
2775 bool UsePoison =
2776 isa<PoisonValue>(Init) &&
2777 STI->canUseExtension(SPIRV::Extension::SPV_KHR_poison_freeze);
2778 if (UsePoison) {
2779 CallInst *Call = B.CreateIntrinsicWithoutFolding(Intrinsic::spv_poison,
2780 {B.getInt32Ty()}, {});
2781 AggrConsts[Call] = cast<PoisonValue>(Init);
2782 AggrConstTypes[Call] = Init->getType();
2783 InitOp = Call;
2784 } else {
2785 InitOp = buildSpvUndefComposite(Init->getType(), B);
2786 }
2787 }
2788 Type *Ty = isAggrConstForceInt32(Init) ? B.getInt32Ty() : Init->getType();
2789 Constant *Const = isAggrConstForceInt32(Init) ? B.getInt32(1) : Init;
2790 CallInst *InitInst = B.CreateIntrinsicWithoutFolding(
2791 Intrinsic::spv_init_global, {GV.getType(), Ty}, {&GV, Const});
2792 InitInst->setArgOperand(1, InitOp);
2793 }
2794 // Globals with only use-list references have no real function uses. Emit
2795 // spv_unref_global so buildGlobalVariable is called for them.
2796 if (!Init && hasOnlyArtificialUses(GV))
2797 B.CreateIntrinsic(Intrinsic::spv_unref_global, GV.getType(), &GV);
2798}
2799
2800// Return true, if we can't decide what is the pointee type now and will get
2801// back to the question later. Return false is spv_assign_ptr_type is not needed
2802// or can be inserted immediately.
2803bool SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I,
2804 IRBuilder<> &B,
2805 bool UnknownElemTypeI8) {
2807 if (!isPointerTy(I->getType()) || !requireAssignType(I))
2808 return false;
2809
2811 if (Type *ElemTy = deduceElementType(I, UnknownElemTypeI8)) {
2812 GR->buildAssignPtr(B, ElemTy, I);
2813 return false;
2814 }
2815 return true;
2816}
2817
2818void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
2819 IRBuilder<> &B) {
2820 // TODO: extend the list of functions with known result types
2821 static StringMap<unsigned> ResTypeWellKnown = {
2822 {"async_work_group_copy", WellKnownTypes::Event},
2823 {"async_work_group_strided_copy", WellKnownTypes::Event},
2824 {"__spirv_GroupAsyncCopy", WellKnownTypes::Event}};
2825
2827
2828 bool IsKnown = false;
2829 if (auto *CI = dyn_cast<CallInst>(I)) {
2830 if (!CI->isIndirectCall() && !CI->isInlineAsm() &&
2831 CI->getCalledFunction() && !CI->getCalledFunction()->isIntrinsic()) {
2832 Function *CalledF = CI->getCalledFunction();
2833 std::string DemangledName =
2835 FPDecorationId DecorationId = FPDecorationId::NONE;
2836 if (DemangledName.length() > 0)
2837 DemangledName =
2838 SPIRV::lookupBuiltinNameHelper(DemangledName, &DecorationId);
2839 auto ResIt = ResTypeWellKnown.find(DemangledName);
2840 if (ResIt != ResTypeWellKnown.end()) {
2841 IsKnown = true;
2843 switch (ResIt->second) {
2844 case WellKnownTypes::Event:
2845 GR->buildAssignType(
2846 B, TargetExtType::get(I->getContext(), "spirv.Event"), I);
2847 break;
2848 }
2849 }
2850 // check if a floating rounding mode or saturation info is present
2851 switch (DecorationId) {
2852 default:
2853 break;
2854 case FPDecorationId::SAT:
2856 break;
2857 case FPDecorationId::RTE:
2859 CI, SPIRV::FPRoundingMode::FPRoundingMode::RTE, B);
2860 break;
2861 case FPDecorationId::RTZ:
2863 CI, SPIRV::FPRoundingMode::FPRoundingMode::RTZ, B);
2864 break;
2865 case FPDecorationId::RTP:
2867 CI, SPIRV::FPRoundingMode::FPRoundingMode::RTP, B);
2868 break;
2869 case FPDecorationId::RTN:
2871 CI, SPIRV::FPRoundingMode::FPRoundingMode::RTN, B);
2872 break;
2873 }
2874 }
2875 }
2876
2877 Type *Ty = I->getType();
2878 if (!IsKnown && !Ty->isVoidTy() && !isPointerTy(Ty) && requireAssignType(I)) {
2880 Type *TypeToAssign = Ty;
2881 if (auto *II = dyn_cast<IntrinsicInst>(I)) {
2882 if (isSpvAggrPlaceholder(II)) {
2883 auto It = AggrConstTypes.find(II);
2884 if (It == AggrConstTypes.end())
2885 report_fatal_error("Unknown composite intrinsic type");
2886 TypeToAssign = It->second;
2887 } else if (II->getIntrinsicID() == Intrinsic::spv_poison) {
2888 if (auto It = AggrConstTypes.find(II); It != AggrConstTypes.end())
2889 TypeToAssign = It->second;
2890 }
2891 } else if (auto It = AggrConstTypes.find(I); It != AggrConstTypes.end())
2892 TypeToAssign = It->second;
2893 TypeToAssign = restoreMutatedType(GR, I, TypeToAssign);
2894 GR->buildAssignType(B, TypeToAssign, I);
2895 }
2896 for (const auto &Op : I->operands()) {
2898 // Check GetElementPtrConstantExpr case.
2900 (isa<GEPOperator>(Op) ||
2901 (cast<ConstantExpr>(Op)->getOpcode() == CastInst::IntToPtr)))) {
2903 Type *OpTy = Op->getType();
2904 if (isa<UndefValue>(Op) && OpTy->isAggregateType()) {
2905 CallInst *AssignCI =
2906 buildIntrWithMD(Intrinsic::spv_assign_type, {B.getInt32Ty()}, Op,
2907 UndefValue::get(B.getInt32Ty()), {}, B);
2908 GR->addAssignPtrTypeInstr(Op, AssignCI);
2909 } else if (!isa<Instruction>(Op)) {
2910 Type *OpTy = Op->getType();
2911 Type *OpTyElem = getPointeeType(OpTy);
2912 if (OpTyElem) {
2913 GR->buildAssignPtr(B, OpTyElem, Op);
2914 } else if (isPointerTy(OpTy)) {
2915 Type *ElemTy = GR->findDeducedElementType(Op);
2916 GR->buildAssignPtr(B, ElemTy ? ElemTy : deduceElementType(Op, true),
2917 Op);
2918 } else {
2919 Value *OpTyVal = Op;
2920 if (OpTy->isTargetExtTy()) {
2921 // We need to do this in order to be consistent with how target ext
2922 // types are handled in `processInstrAfterVisit`
2923 OpTyVal = getNormalizedPoisonValue(OpTy);
2924 }
2925 CallInst *AssignCI =
2926 buildIntrWithMD(Intrinsic::spv_assign_type, {OpTy},
2927 getNormalizedPoisonValue(OpTy), OpTyVal, {}, B);
2928 GR->addAssignPtrTypeInstr(OpTyVal, AssignCI);
2929 }
2930 }
2931 }
2932 }
2933}
2934
2935bool SPIRVEmitIntrinsics::shouldTryToAddMemAliasingDecoration(
2936 Instruction *Inst) {
2937 const SPIRVSubtarget *STI = TM.getSubtargetImpl(*Inst->getFunction());
2938 if (!STI->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing))
2939 return false;
2940 // Add aliasing decorations to internal load and store intrinsics.
2941 // Do not attach them to store atomic or load atomic intrinsics / instructions
2942 // since the extension is inconsistent at the moment (we cannot add the
2943 // decoration to atomic stores because they do not have an id).
2944 return match(Inst,
2946}
2947
2948void SPIRVEmitIntrinsics::insertSpirvDecorations(Instruction *I,
2949 IRBuilder<> &B) {
2950 if (MDNode *MD = I->getMetadata("spirv.Decorations")) {
2952 B.CreateIntrinsic(Intrinsic::spv_assign_decoration, {I->getType()},
2953 {I, MetadataAsValue::get(I->getContext(), MD)});
2954 }
2955 // Lower alias.scope/noalias metadata
2956 {
2957 auto processMemAliasingDecoration = [&](unsigned Kind) {
2958 if (MDNode *AliasListMD = I->getMetadata(Kind)) {
2959 if (shouldTryToAddMemAliasingDecoration(I)) {
2960 uint32_t Dec = Kind == LLVMContext::MD_alias_scope
2961 ? SPIRV::Decoration::AliasScopeINTEL
2962 : SPIRV::Decoration::NoAliasINTEL;
2964 I, ConstantInt::get(B.getInt32Ty(), Dec),
2965 MetadataAsValue::get(I->getContext(), AliasListMD)};
2967 B.CreateIntrinsic(Intrinsic::spv_assign_aliasing_decoration,
2968 {I->getType()}, {Args});
2969 }
2970 }
2971 };
2972 processMemAliasingDecoration(LLVMContext::MD_alias_scope);
2973 processMemAliasingDecoration(LLVMContext::MD_noalias);
2974 }
2975 // MD_fpmath
2976 if (MDNode *MD = I->getMetadata(LLVMContext::MD_fpmath)) {
2977 const SPIRVSubtarget *STI = TM.getSubtargetImpl(*I->getFunction());
2978 bool AllowFPMaxError =
2979 STI->canUseExtension(SPIRV::Extension::SPV_INTEL_fp_max_error);
2980 if (!AllowFPMaxError)
2981 return;
2982
2984 B.CreateIntrinsic(Intrinsic::spv_assign_fpmaxerror_decoration,
2985 {I->getType()},
2986 {I, MetadataAsValue::get(I->getContext(), MD)});
2987 }
2988 if (I->getModule()->getTargetTriple().getVendor() == Triple::AMD &&
2990 // If present, we encode AMDGPU atomic metadata as UserSemantic string
2991 // decorations, which will be parsed during reverse translation.
2992 auto &Ctx = B.getContext();
2993 auto *US = ConstantAsMetadata::get(
2994 ConstantInt::get(B.getInt32Ty(), SPIRV::Decoration::UserSemantic));
2995
2997 if (I->hasMetadata("amdgpu.no.fine.grained.memory"))
2999 Ctx, {US, MDString::get(Ctx, "amdgpu.no.fine.grained.memory")}));
3000 if (I->hasMetadata("amdgpu.no.remote.memory"))
3002 Ctx, {US, MDString::get(Ctx, "amdgpu.no.remote.memory")}));
3003 if (I->hasMetadata("amdgpu.ignore.denormal.mode"))
3005 Ctx, {US, MDString::get(Ctx, "amdgpu.ignore.denormal.mode")}));
3006 if (!MDs.empty())
3007 B.CreateIntrinsic(Intrinsic::spv_assign_decoration, {I->getType()},
3008 {I, MetadataAsValue::get(Ctx, MDNode::get(Ctx, MDs))});
3009 }
3010}
3011
3013 const Module &M,
3015 &FPFastMathDefaultInfoMap,
3016 Function *F) {
3017 auto it = FPFastMathDefaultInfoMap.find(F);
3018 if (it != FPFastMathDefaultInfoMap.end())
3019 return it->second;
3020
3021 // If the map does not contain the entry, create a new one. Initialize it to
3022 // contain all 3 elements sorted by bit width of target type: {half, float,
3023 // double}.
3024 SPIRV::FPFastMathDefaultInfoVector FPFastMathDefaultInfoVec;
3025 FPFastMathDefaultInfoVec.emplace_back(Type::getHalfTy(M.getContext()),
3026 SPIRV::FPFastMathMode::None);
3027 FPFastMathDefaultInfoVec.emplace_back(Type::getFloatTy(M.getContext()),
3028 SPIRV::FPFastMathMode::None);
3029 FPFastMathDefaultInfoVec.emplace_back(Type::getDoubleTy(M.getContext()),
3030 SPIRV::FPFastMathMode::None);
3031 return FPFastMathDefaultInfoMap[F] = std::move(FPFastMathDefaultInfoVec);
3032}
3033
3035 SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec,
3036 const Type *Ty) {
3037 size_t BitWidth = Ty->getScalarSizeInBits();
3038 int Index =
3040 BitWidth);
3041 assert(Index >= 0 && Index < 3 &&
3042 "Expected FPFastMathDefaultInfo for half, float, or double");
3043 assert(FPFastMathDefaultInfoVec.size() == 3 &&
3044 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3045 return FPFastMathDefaultInfoVec[Index];
3046}
3047
3048void SPIRVEmitIntrinsics::insertConstantsForFPFastMathDefault(Module &M) {
3049 const SPIRVSubtarget *ST = TM.getSubtargetImpl();
3050 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2))
3051 return;
3052
3053 // Store the FPFastMathDefaultInfo in the FPFastMathDefaultInfoMap.
3054 // We need the entry point (function) as the key, and the target
3055 // type and flags as the value.
3056 // We also need to check ContractionOff and SignedZeroInfNanPreserve
3057 // execution modes, as they are now deprecated and must be replaced
3058 // with FPFastMathDefaultInfo.
3059 auto Node = M.getNamedMetadata("spirv.ExecutionMode");
3060 if (!Node) {
3061 if (!M.getNamedMetadata("opencl.enable.FP_CONTRACT")) {
3062 // This requires emitting ContractionOff. However, because
3063 // ContractionOff is now deprecated, we need to replace it with
3064 // FPFastMathDefaultInfo with FP Fast Math Mode bitmask set to all 0.
3065 // We need to create the constant for that.
3066
3067 // Create constant instruction with the bitmask flags.
3068 Constant *InitValue =
3069 ConstantInt::get(Type::getInt32Ty(M.getContext()), 0);
3070 // TODO: Reuse constant if there is one already with the required
3071 // value.
3072 [[maybe_unused]] GlobalVariable *GV =
3073 new GlobalVariable(M, // Module
3074 Type::getInt32Ty(M.getContext()), // Type
3075 true, // isConstant
3077 InitValue // Initializer
3078 );
3079 }
3080 return;
3081 }
3082
3083 // The table maps function pointers to their default FP fast math info. It
3084 // can be assumed that the SmallVector is sorted by the bit width of the
3085 // type. The first element is the smallest bit width, and the last element
3086 // is the largest bit width, therefore, we will have {half, float, double}
3087 // in the order of their bit widths.
3088 DenseMap<Function *, SPIRV::FPFastMathDefaultInfoVector>
3089 FPFastMathDefaultInfoMap;
3090
3091 for (unsigned i = 0; i < Node->getNumOperands(); i++) {
3092 MDNode *MDN = cast<MDNode>(Node->getOperand(i));
3093 assert(MDN->getNumOperands() >= 2 && "Expected at least 2 operands");
3095 cast<ConstantAsMetadata>(MDN->getOperand(0))->getValue());
3096 const auto EM =
3098 cast<ConstantAsMetadata>(MDN->getOperand(1))->getValue())
3099 ->getZExtValue();
3100 if (EM == SPIRV::ExecutionMode::FPFastMathDefault) {
3101 assert(MDN->getNumOperands() == 4 &&
3102 "Expected 4 operands for FPFastMathDefault");
3103 const Type *T = cast<ValueAsMetadata>(MDN->getOperand(2))->getType();
3104 unsigned Flags =
3106 cast<ConstantAsMetadata>(MDN->getOperand(3))->getValue())
3107 ->getZExtValue();
3108 SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec =
3109 getOrCreateFPFastMathDefaultInfoVec(M, FPFastMathDefaultInfoMap, F);
3110 SPIRV::FPFastMathDefaultInfo &Info =
3111 getFPFastMathDefaultInfo(FPFastMathDefaultInfoVec, T);
3112 Info.FastMathFlags = Flags;
3113 Info.FPFastMathDefault = true;
3114 } else if (EM == SPIRV::ExecutionMode::ContractionOff) {
3115 assert(MDN->getNumOperands() == 2 &&
3116 "Expected no operands for ContractionOff");
3117
3118 // We need to save this info for every possible FP type, i.e. {half,
3119 // float, double, fp128}.
3120 SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec =
3121 getOrCreateFPFastMathDefaultInfoVec(M, FPFastMathDefaultInfoMap, F);
3122 for (SPIRV::FPFastMathDefaultInfo &Info : FPFastMathDefaultInfoVec) {
3123 Info.ContractionOff = true;
3124 }
3125 } else if (EM == SPIRV::ExecutionMode::SignedZeroInfNanPreserve) {
3126 assert(MDN->getNumOperands() == 3 &&
3127 "Expected 1 operand for SignedZeroInfNanPreserve");
3128 unsigned TargetWidth =
3130 cast<ConstantAsMetadata>(MDN->getOperand(2))->getValue())
3131 ->getZExtValue();
3132 // We need to save this info only for the FP type with TargetWidth.
3133 SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec =
3134 getOrCreateFPFastMathDefaultInfoVec(M, FPFastMathDefaultInfoMap, F);
3137 assert(Index >= 0 && Index < 3 &&
3138 "Expected FPFastMathDefaultInfo for half, float, or double");
3139 assert(FPFastMathDefaultInfoVec.size() == 3 &&
3140 "Expected FPFastMathDefaultInfoVec to have exactly 3 elements");
3141 FPFastMathDefaultInfoVec[Index].SignedZeroInfNanPreserve = true;
3142 }
3143 }
3144
3145 DenseMap<unsigned, GlobalVariable *> GlobalVars;
3146 for (auto &[Func, FPFastMathDefaultInfoVec] : FPFastMathDefaultInfoMap) {
3147 if (FPFastMathDefaultInfoVec.empty())
3148 continue;
3149
3150 for (const SPIRV::FPFastMathDefaultInfo &Info : FPFastMathDefaultInfoVec) {
3151 assert(Info.Ty && "Expected target type for FPFastMathDefaultInfo");
3152 // Skip if none of the execution modes was used.
3153 unsigned Flags = Info.FastMathFlags;
3154 if (Flags == SPIRV::FPFastMathMode::None && !Info.ContractionOff &&
3155 !Info.SignedZeroInfNanPreserve && !Info.FPFastMathDefault)
3156 continue;
3157
3158 // Check if flags are compatible.
3159 if (Info.ContractionOff && (Flags & SPIRV::FPFastMathMode::AllowContract))
3160 report_fatal_error("Conflicting FPFastMathFlags: ContractionOff "
3161 "and AllowContract");
3162
3163 if (Info.SignedZeroInfNanPreserve &&
3164 !(Flags &
3165 (SPIRV::FPFastMathMode::NotNaN | SPIRV::FPFastMathMode::NotInf |
3166 SPIRV::FPFastMathMode::NSZ))) {
3167 if (Info.FPFastMathDefault)
3168 report_fatal_error("Conflicting FPFastMathFlags: "
3169 "SignedZeroInfNanPreserve but at least one of "
3170 "NotNaN/NotInf/NSZ is enabled.");
3171 }
3172
3173 if ((Flags & SPIRV::FPFastMathMode::AllowTransform) &&
3174 !((Flags & SPIRV::FPFastMathMode::AllowReassoc) &&
3175 (Flags & SPIRV::FPFastMathMode::AllowContract))) {
3176 report_fatal_error("Conflicting FPFastMathFlags: "
3177 "AllowTransform requires AllowReassoc and "
3178 "AllowContract to be set.");
3179 }
3180
3181 auto it = GlobalVars.find(Flags);
3182 GlobalVariable *GV = nullptr;
3183 if (it != GlobalVars.end()) {
3184 // Reuse existing global variable.
3185 GV = it->second;
3186 } else {
3187 // Create constant instruction with the bitmask flags.
3188 Constant *InitValue =
3189 ConstantInt::get(Type::getInt32Ty(M.getContext()), Flags);
3190 // TODO: Reuse constant if there is one already with the required
3191 // value.
3192 GV = new GlobalVariable(M, // Module
3193 Type::getInt32Ty(M.getContext()), // Type
3194 true, // isConstant
3196 InitValue // Initializer
3197 );
3198 GlobalVars[Flags] = GV;
3199 }
3200 }
3201 }
3202}
3203
3204void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
3205 IRBuilder<> &B) {
3206 auto *II = dyn_cast<IntrinsicInst>(I);
3207 bool IsConstComposite =
3208 II && II->getIntrinsicID() == Intrinsic::spv_const_composite;
3209 if (IsConstComposite && TrackConstants) {
3211 auto t = AggrConsts.find(I);
3212 assert(t != AggrConsts.end());
3213 auto *NewOp =
3214 buildIntrWithMD(Intrinsic::spv_track_constant,
3215 {II->getType(), II->getType()}, t->second, I, {}, B);
3216 replaceAllUsesWith(I, NewOp, false);
3217 NewOp->setArgOperand(0, I);
3218 }
3219 bool IsPhi = isa<PHINode>(I), BPrepared = false;
3220 for (const auto &Op : I->operands()) {
3221 if (isa<PHINode>(I) || isa<SwitchInst>(I) ||
3223 continue;
3224 unsigned OpNo = Op.getOperandNo();
3225 if (II && ((II->getIntrinsicID() == Intrinsic::spv_gep && OpNo == 0) ||
3226 (!II->isBundleOperand(OpNo) &&
3227 II->paramHasAttr(OpNo, Attribute::ImmArg))))
3228 continue;
3229
3230 if (!BPrepared) {
3231 IsPhi ? B.SetInsertPointPastAllocas(I->getParent()->getParent())
3232 : B.SetInsertPoint(I);
3233 BPrepared = true;
3234 }
3235 Type *OpTy = Op->getType();
3236 Type *OpElemTy = GR->findDeducedElementType(Op);
3237 Value *NewOp = Op;
3238 if (OpTy->isTargetExtTy()) {
3239 // Since this value is replaced by poison, we need to do the same in
3240 // `insertAssignTypeIntrs`.
3241 Value *OpTyVal = getNormalizedPoisonValue(OpTy);
3242 NewOp = buildIntrWithMD(Intrinsic::spv_track_constant,
3243 {OpTy, OpTyVal->getType()}, Op, OpTyVal, {}, B);
3244 }
3245 if (!IsConstComposite && isPointerTy(OpTy) && OpElemTy != nullptr &&
3246 OpElemTy != IntegerType::getInt8Ty(I->getContext())) {
3247 SmallVector<Type *, 2> Types = {OpTy, OpTy};
3248 SmallVector<Value *, 2> Args = {
3249 NewOp, buildMD(getNormalizedPoisonValue(OpElemTy)),
3250 B.getInt32(getPointerAddressSpace(OpTy))};
3251 CallInst *PtrCasted = B.CreateIntrinsicWithoutFolding(
3252 Intrinsic::spv_ptrcast, {Types}, Args);
3253 GR->buildAssignPtr(B, OpElemTy, PtrCasted);
3254 NewOp = PtrCasted;
3255 }
3256 if (NewOp != Op)
3257 I->setOperand(OpNo, NewOp);
3258 }
3259 if (Named.insert(I).second)
3260 emitAssignName(I, B);
3261}
3262
3263Type *SPIRVEmitIntrinsics::deduceFunParamElementType(Function *F,
3264 unsigned OpIdx) {
3265 SmallPtrSet<Function *, 0> FVisited;
3266 return deduceFunParamElementType(F, OpIdx, FVisited);
3267}
3268
3269Type *SPIRVEmitIntrinsics::deduceFunParamElementType(
3270 Function *F, unsigned OpIdx, SmallPtrSetImpl<Function *> &FVisited) {
3271 // maybe a cycle
3272 if (!FVisited.insert(F).second)
3273 return nullptr;
3274
3275 SmallPtrSet<Value *, 0> Visited;
3277 // search in function's call sites
3278 for (User *U : F->users()) {
3279 CallInst *CI = dyn_cast<CallInst>(U);
3280 if (!CI || OpIdx >= CI->arg_size())
3281 continue;
3282 Value *OpArg = CI->getArgOperand(OpIdx);
3283 if (!isPointerTy(OpArg->getType()))
3284 continue;
3285 // maybe we already know operand's element type
3286 if (Type *KnownTy = GR->findDeducedElementType(OpArg))
3287 return KnownTy;
3288 // try to deduce from the operand itself
3289 Visited.clear();
3290 if (Type *Ty = deduceElementTypeHelper(OpArg, Visited, false))
3291 return Ty;
3292 // search in actual parameter's users
3293 for (User *OpU : OpArg->users()) {
3295 if (!Inst || Inst == CI)
3296 continue;
3297 Visited.clear();
3298 if (Type *Ty = deduceElementTypeHelper(Inst, Visited, false))
3299 return Ty;
3300 }
3301 // check if it's a formal parameter of the outer function
3302 if (!CI->getParent() || !CI->getParent()->getParent())
3303 continue;
3304 Function *OuterF = CI->getParent()->getParent();
3305 if (FVisited.find(OuterF) != FVisited.end())
3306 continue;
3307 for (unsigned i = 0; i < OuterF->arg_size(); ++i) {
3308 if (OuterF->getArg(i) == OpArg) {
3309 Lookup.push_back(std::make_pair(OuterF, i));
3310 break;
3311 }
3312 }
3313 }
3314
3315 // search in function parameters
3316 for (auto &Pair : Lookup) {
3317 if (Type *Ty = deduceFunParamElementType(Pair.first, Pair.second, FVisited))
3318 return Ty;
3319 }
3320
3321 return nullptr;
3322}
3323
3324void SPIRVEmitIntrinsics::processParamTypesByFunHeader(Function *F,
3325 IRBuilder<> &B) {
3326 B.SetInsertPointPastAllocas(F);
3327 for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) {
3328 Argument *Arg = F->getArg(OpIdx);
3329 // Vector-of-pointers arg: deduce pointee from a GEP user so the function
3330 // type isn't emitted with the default i8 pointee.
3331 if (isUntypedPointerVectorTy(Arg->getType()) &&
3332 !GR->findDeducedElementType(Arg)) {
3333 for (User *U : Arg->users()) {
3335 if (GEP && GEP->getPointerOperand() == Arg) {
3336 GR->buildAssignPtr(B, GEP->getSourceElementType(), Arg);
3337 break;
3338 }
3339 }
3340 continue;
3341 }
3342 if (!isUntypedPointerTy(Arg->getType()))
3343 continue;
3344 Type *ElemTy = GR->findDeducedElementType(Arg);
3345 if (ElemTy)
3346 continue;
3347 if (hasPointeeTypeAttr(Arg) &&
3348 (ElemTy = getPointeeTypeByAttr(Arg)) != nullptr) {
3349 GR->buildAssignPtr(B, ElemTy, Arg);
3350 continue;
3351 }
3352 // search in function's call sites
3353 for (User *U : F->users()) {
3354 CallInst *CI = dyn_cast<CallInst>(U);
3355 if (!CI || OpIdx >= CI->arg_size())
3356 continue;
3357 Value *OpArg = CI->getArgOperand(OpIdx);
3358 if (!isPointerTy(OpArg->getType()))
3359 continue;
3360 // maybe we already know operand's element type
3361 if ((ElemTy = GR->findDeducedElementType(OpArg)) != nullptr)
3362 break;
3363 }
3364 if (ElemTy) {
3365 GR->buildAssignPtr(B, ElemTy, Arg);
3366 continue;
3367 }
3368 if (HaveFunPtrs) {
3369 for (User *U : Arg->users()) {
3370 CallInst *CI = dyn_cast<CallInst>(U);
3371 if (CI && !isa<IntrinsicInst>(CI) && CI->isIndirectCall() &&
3372 CI->getCalledOperand() == Arg &&
3373 CI->getParent()->getParent() == CurrF) {
3375 deduceOperandElementTypeFunctionPointer(CI, Ops, ElemTy, false);
3376 if (ElemTy) {
3377 GR->buildAssignPtr(B, ElemTy, Arg);
3378 break;
3379 }
3380 }
3381 }
3382 }
3383 }
3384}
3385
3386void SPIRVEmitIntrinsics::processParamTypes(Function *F, IRBuilder<> &B) {
3387 B.SetInsertPointPastAllocas(F);
3388 for (unsigned OpIdx = 0; OpIdx < F->arg_size(); ++OpIdx) {
3389 Argument *Arg = F->getArg(OpIdx);
3390 if (!isUntypedPointerTy(Arg->getType()))
3391 continue;
3392 Type *ElemTy = GR->findDeducedElementType(Arg);
3393 if (!ElemTy && (ElemTy = deduceFunParamElementType(F, OpIdx)) != nullptr) {
3394 if (CallInst *AssignCI = GR->findAssignPtrTypeInstr(Arg)) {
3395 DenseSet<std::pair<Value *, Value *>> VisitedSubst;
3396 GR->updateAssignType(AssignCI, Arg, getNormalizedPoisonValue(ElemTy));
3397 propagateElemType(Arg, IntegerType::getInt8Ty(F->getContext()),
3398 VisitedSubst);
3399 } else {
3400 GR->buildAssignPtr(B, ElemTy, Arg);
3401 }
3402 }
3403 }
3404}
3405
3407 SPIRVGlobalRegistry *GR) {
3408 FunctionType *FTy = F->getFunctionType();
3409 bool IsNewFTy = false;
3411 for (Argument &Arg : F->args()) {
3412 Type *ArgTy = Arg.getType();
3413 if (ArgTy->isPointerTy())
3414 if (Type *ElemTy = GR->findDeducedElementType(&Arg)) {
3415 IsNewFTy = true;
3416 ArgTy = getTypedPointerWrapper(ElemTy, getPointerAddressSpace(ArgTy));
3417 }
3418 ArgTys.push_back(ArgTy);
3419 }
3420 return IsNewFTy
3421 ? FunctionType::get(FTy->getReturnType(), ArgTys, FTy->isVarArg())
3422 : FTy;
3423}
3424
3425bool SPIRVEmitIntrinsics::processFunctionPointers(Module &M) {
3426 SmallVector<Function *> Worklist;
3427 for (auto &F : M) {
3428 if (F.isIntrinsic())
3429 continue;
3430 if (F.isDeclaration()) {
3431 for (User *U : F.users()) {
3432 CallInst *CI = dyn_cast<CallInst>(U);
3433 if (!CI || CI->getCalledFunction() != &F) {
3434 Worklist.push_back(&F);
3435 break;
3436 }
3437 }
3438 } else {
3439 if (F.user_empty())
3440 continue;
3441 Type *FPElemTy = GR->findDeducedElementType(&F);
3442 if (!FPElemTy)
3443 FPElemTy = getFunctionPointerElemType(&F, GR);
3444 for (User *U : F.users()) {
3445 IntrinsicInst *II = dyn_cast<IntrinsicInst>(U);
3446 if (!II || II->arg_size() != 3 || II->getOperand(0) != &F)
3447 continue;
3448 if (II->getIntrinsicID() == Intrinsic::spv_assign_ptr_type ||
3449 II->getIntrinsicID() == Intrinsic::spv_ptrcast) {
3451 break;
3452 }
3453 }
3454 }
3455 }
3456 if (Worklist.empty())
3457 return false;
3458
3459 LLVMContext &Ctx = M.getContext();
3461 BasicBlock *BB = BasicBlock::Create(Ctx, "entry", SF);
3462 IRBuilder<> IRB(BB);
3463
3464 for (Function *F : Worklist) {
3466 for (const auto &Arg : F->args())
3467 Args.push_back(getNormalizedPoisonValue(Arg.getType()));
3468 IRB.CreateCall(F, Args);
3469 }
3470 IRB.CreateRetVoid();
3471
3472 return true;
3473}
3474
3475// Apply types parsed from demangled function declarations.
3476void SPIRVEmitIntrinsics::applyDemangledPtrArgTypes(IRBuilder<> &B) {
3477 DenseMap<Function *, CallInst *> Ptrcasts;
3478 for (auto It : FDeclPtrTys) {
3479 Function *F = It.first;
3480 for (auto *U : F->users()) {
3481 CallInst *CI = dyn_cast<CallInst>(U);
3482 if (!CI || CI->getCalledFunction() != F)
3483 continue;
3484 unsigned Sz = CI->arg_size();
3485 for (auto [Idx, ElemTy] : It.second) {
3486 if (Idx >= Sz)
3487 continue;
3488 Value *Param = CI->getArgOperand(Idx);
3489 if (GR->findDeducedElementType(Param) || isa<GlobalValue>(Param))
3490 continue;
3491 if (Argument *Arg = dyn_cast<Argument>(Param)) {
3492 if (!hasPointeeTypeAttr(Arg)) {
3493 B.SetInsertPointPastAllocas(Arg->getParent());
3494 B.SetCurrentDebugLocation(DebugLoc());
3495 GR->buildAssignPtr(B, ElemTy, Arg);
3496 }
3497 } else if (isaGEP(Param)) {
3498 replaceUsesOfWithSpvPtrcast(Param, normalizeType(ElemTy), CI,
3499 Ptrcasts);
3500 } else if (isa<Instruction>(Param)) {
3501 GR->addDeducedElementType(Param, normalizeType(ElemTy));
3502 // insertAssignTypeIntrs() will complete buildAssignPtr()
3503 } else {
3504 B.SetInsertPoint(CI->getParent()
3505 ->getParent()
3506 ->getEntryBlock()
3507 .getFirstNonPHIOrDbgOrAlloca());
3508 GR->buildAssignPtr(B, ElemTy, Param);
3509 }
3510 CallInst *Ref = dyn_cast<CallInst>(Param);
3511 if (!Ref)
3512 continue;
3513 Function *RefF = Ref->getCalledFunction();
3514 if (!RefF || !isPointerTy(RefF->getReturnType()) ||
3515 GR->findDeducedElementType(RefF))
3516 continue;
3517 ElemTy = normalizeType(ElemTy);
3518 GR->addDeducedElementType(RefF, ElemTy);
3519 GR->addReturnType(
3521 ElemTy, getPointerAddressSpace(RefF->getReturnType())));
3522 }
3523 }
3524 }
3525}
3526
3527GetElementPtrInst *
3528SPIRVEmitIntrinsics::simplifyZeroLengthArrayGepInst(GetElementPtrInst *GEP) {
3529 // getelementptr [0 x T], P, 0 (zero), I -> getelementptr T, P, I.
3530 // If type is 0-length array and first index is 0 (zero), drop both the
3531 // 0-length array type and the first index. This is a common pattern in
3532 // the IR, e.g. when using a zero-length array as a placeholder for a
3533 // flexible array such as unbound arrays.
3534 assert(GEP && "GEP is null");
3535 Type *SrcTy = GEP->getSourceElementType();
3536 SmallVector<Value *, 8> Indices(GEP->indices());
3537 ArrayType *ArrTy = dyn_cast<ArrayType>(SrcTy);
3538 if (ArrTy && ArrTy->getNumElements() == 0 && match(Indices[0], m_Zero())) {
3539 Indices.erase(Indices.begin());
3540 SrcTy = ArrTy->getElementType();
3541 return GetElementPtrInst::Create(SrcTy, GEP->getPointerOperand(), Indices,
3542 GEP->getNoWrapFlags(), "",
3543 GEP->getIterator());
3544 }
3545 return nullptr;
3546}
3547
3548void SPIRVEmitIntrinsics::emitUnstructuredLoopControls(Function &F,
3549 IRBuilder<> &B) {
3550 const SPIRVSubtarget *ST = TM.getSubtargetImpl(F);
3551 // Shaders use SPIRVStructurizer which emits OpLoopMerge via spv_loop_merge.
3552 if (ST->isShader())
3553 return;
3554
3555 if (ST->canUseExtension(
3556 SPIRV::Extension::SPV_INTEL_unstructured_loop_controls)) {
3557 for (BasicBlock &BB : F) {
3559 MDNode *LoopMD = Term->getMetadata(LLVMContext::MD_loop);
3560 if (!LoopMD)
3561 continue;
3562
3563 SmallVector<unsigned, 1> Ops =
3565 unsigned LC = Ops[0];
3566 if (LC == SPIRV::LoopControl::None)
3567 continue;
3568
3569 // Emit intrinsic: loop control mask + optional parameters.
3570 B.SetInsertPoint(Term);
3571 SmallVector<Value *, 4> IntrArgs;
3572 for (unsigned Op : Ops)
3573 IntrArgs.push_back(B.getInt32(Op));
3574 B.CreateIntrinsic(Intrinsic::spv_loop_control_intel, IntrArgs);
3575 }
3576 return;
3577 }
3578
3579 // For non-shader targets without the Intel extension, emit OpLoopMerge
3580 // using spv_loop_merge intrinsics, mirroring the structurizer approach.
3581 DominatorTree DT(F);
3582 LoopInfo LI(DT);
3583 if (LI.empty())
3584 return;
3585
3586 for (Loop *L : LI.getLoopsInPreorder()) {
3587 BasicBlock *Latch = L->getLoopLatch();
3588 if (!Latch)
3589 continue;
3590 BasicBlock *MergeBlock = L->getUniqueExitBlock();
3591 if (!MergeBlock)
3592 continue;
3593
3594 // Check for loop unroll metadata on the latch terminator.
3595 SmallVector<unsigned, 1> LoopControlOps =
3597 if (LoopControlOps[0] == SPIRV::LoopControl::None)
3598 continue;
3599
3600 BasicBlock *Header = L->getHeader();
3601 B.SetInsertPoint(Header->getTerminator());
3602 auto *MergeAddress = BlockAddress::get(&F, MergeBlock);
3603 auto *ContinueAddress = BlockAddress::get(&F, Latch);
3604 SmallVector<Value *, 4> Args = {MergeAddress, ContinueAddress};
3605 for (unsigned Imm : LoopControlOps)
3606 Args.emplace_back(B.getInt32(Imm));
3607 B.CreateIntrinsic(Intrinsic::spv_loop_merge, {Args});
3608 }
3609}
3610
3611bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
3612 if (Func.isDeclaration())
3613 return false;
3614
3615 const SPIRVSubtarget &ST = TM.getSubtarget<SPIRVSubtarget>(Func);
3616 GR = ST.getSPIRVGlobalRegistry();
3617
3618 if (!CurrF)
3619 HaveFunPtrs =
3620 ST.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers);
3621
3622 CurrF = &Func;
3623 IRBuilder<> B(Func.getContext());
3624 AggrConsts.clear();
3625 AggrConstTypes.clear();
3626 AggrStores.clear();
3627
3628 processParamTypesByFunHeader(CurrF, B);
3629
3630 // Fix GEP result types ahead of inference, and simplify if possible.
3631 // Data structure for dead instructions that were simplified and replaced.
3632 SmallPtrSet<Instruction *, 4> DeadInsts;
3633 for (auto &I : instructions(Func)) {
3635 auto *SGEP = dyn_cast<StructuredGEPInst>(&I);
3636
3637 if ((!GEP && !SGEP) || GR->findDeducedElementType(&I))
3638 continue;
3639
3640 if (SGEP) {
3641 GR->addDeducedElementType(SGEP,
3642 normalizeType(SGEP->getResultElementType()));
3643 continue;
3644 }
3645
3646 GetElementPtrInst *NewGEP = simplifyZeroLengthArrayGepInst(GEP);
3647 if (NewGEP) {
3648 GEP->replaceAllUsesWith(NewGEP);
3649 DeadInsts.insert(GEP);
3650 GEP = NewGEP;
3651 }
3652 if (Type *GepTy = getGEPType(GEP))
3653 GR->addDeducedElementType(GEP, normalizeType(GepTy));
3654 }
3655 // Remove dead instructions that were simplified and replaced.
3656 for (auto *I : DeadInsts) {
3657 assert(I->use_empty() && "Dead instruction should not have any uses left");
3658 I->eraseFromParent();
3659 }
3660
3661 // StoreInst's operand type can be changed during the next
3662 // transformations, so we need to store it in the set. Also store already
3663 // transformed types.
3664 for (auto &I : instructions(Func)) {
3665 StoreInst *SI = dyn_cast<StoreInst>(&I);
3666 if (!SI)
3667 continue;
3668 Type *ElTy = SI->getValueOperand()->getType();
3669 if (ElTy->isAggregateType() || ElTy->isVectorTy())
3670 AggrStores.insert(&I);
3671 }
3672
3673 B.SetInsertPoint(&Func.getEntryBlock(), Func.getEntryBlock().begin());
3674 for (auto &GV : Func.getParent()->globals())
3675 processGlobalValue(GV, B);
3676
3677 reconstructAggregateReturns(Func, B);
3678 preprocessUndefsAndPoisons(B);
3679 simplifyNullAddrSpaceCasts();
3680 preprocessCompositeConstants(B);
3681
3682 // A PHINode, SelectInst or FreezeInst takes its result type from its
3683 // operands. Aggregate arms are lowered to i32 value-ids (composite constants
3684 // here, loads and other producers during the visitor pass below), so mutate
3685 // an aggregate PHI, select or freeze to match. The original type is tracked
3686 // in AggrConstTypes (used to assign the SPIR-V type) and its extractvalue
3687 // users are lowered to spv_extractv.
3688 Type *I32Ty = B.getInt32Ty();
3689 for (Instruction &I : instructions(Func)) {
3691 continue;
3692 // Give multi-register arms a value-id first, before the result is mutated.
3693 insertCompositeAggregateArms(&I, B);
3694 AggrConstTypes[&I] = I.getType();
3695 I.mutateType(I32Ty);
3696 }
3697
3698 preprocessBoolVectorBitcasts(Func);
3701
3702 applyDemangledPtrArgTypes(B);
3703
3704 // Pass forward: use operand to deduce instructions result.
3705 for (auto &I : Worklist) {
3706 // Don't emit intrinsincs for convergence intrinsics.
3707 if (isConvergenceIntrinsic(I))
3708 continue;
3709
3710 bool Postpone = insertAssignPtrTypeIntrs(I, B, false);
3711 // if Postpone is true, we can't decide on pointee type yet
3712 insertAssignTypeIntrs(I, B);
3713 insertPtrCastOrAssignTypeInstr(I, B);
3715 // if instruction requires a pointee type set, let's check if we know it
3716 // already, and force it to be i8 if not
3717 if (Postpone && !GR->findAssignPtrTypeInstr(I))
3718 insertAssignPtrTypeIntrs(I, B, true);
3719
3720 if (auto *FPI = dyn_cast<ConstrainedFPIntrinsic>(I))
3721 useRoundingMode(FPI, B);
3722 }
3723
3724 // Pass backward: use instructions results to specify/update/cast operands
3725 // where needed.
3726 SmallPtrSet<Instruction *, 4> IncompleteRets;
3727 for (auto &I : llvm::reverse(instructions(Func)))
3728 deduceOperandElementType(&I, &IncompleteRets);
3729
3730 // Pass forward for PHIs only, their operands are not preceed the
3731 // instruction in meaning of `instructions(Func)`.
3732 for (BasicBlock &BB : Func)
3733 for (PHINode &Phi : BB.phis())
3734 if (isPointerTy(Phi.getType()))
3735 deduceOperandElementType(&Phi, nullptr);
3736
3737 for (auto *I : Worklist) {
3738 TrackConstants = true;
3739 if (!I->getType()->isVoidTy() || isa<StoreInst>(I))
3741 // Visitors return either the original/newly created instruction for
3742 // further processing, nullptr otherwise.
3743 I = visit(*I);
3744 if (!I)
3745 continue;
3746
3747 // Don't emit intrinsics for convergence operations.
3748 if (isConvergenceIntrinsic(I))
3749 continue;
3750
3752 processInstrAfterVisit(I, B);
3753 }
3754
3755 emitUnstructuredLoopControls(Func, B);
3756
3757 return true;
3758}
3759
3760// Try to deduce a better type for pointers to untyped ptr.
3761bool SPIRVEmitIntrinsics::postprocessTypes(Module &M) {
3762 if (!GR || TodoTypeSz == 0)
3763 return false;
3764
3765 unsigned SzTodo = TodoTypeSz;
3766 DenseMap<Value *, SmallPtrSet<Value *, 4>> ToProcess;
3767 for (auto [Op, Enabled] : TodoType) {
3768 // TODO: add isa<CallInst>(Op) to continue
3769 if (!Enabled || isaGEP(Op))
3770 continue;
3771 CallInst *AssignCI = GR->findAssignPtrTypeInstr(Op);
3772 Type *KnownTy = GR->findDeducedElementType(Op);
3773 if (!KnownTy || !AssignCI)
3774 continue;
3775 assert(Op == AssignCI->getArgOperand(0));
3776 // Try to improve the type deduced after all Functions are processed.
3777 if (auto *CI = dyn_cast<Instruction>(Op)) {
3778 CurrF = CI->getParent()->getParent();
3779 SmallPtrSet<Value *, 0> Visited;
3780 if (Type *ElemTy = deduceElementTypeHelper(Op, Visited, false, true)) {
3781 if (ElemTy != KnownTy) {
3782 DenseSet<std::pair<Value *, Value *>> VisitedSubst;
3783 propagateElemType(CI, ElemTy, VisitedSubst);
3784 eraseTodoType(Op);
3785 continue;
3786 }
3787 }
3788 }
3789
3790 if (Op->hasUseList()) {
3791 for (User *U : Op->users()) {
3793 if (Inst && !isa<IntrinsicInst>(Inst))
3794 ToProcess[Inst].insert(Op);
3795 }
3796 }
3797 }
3798 if (TodoTypeSz == 0)
3799 return true;
3800
3801 for (auto &F : M) {
3802 CurrF = &F;
3803 SmallPtrSet<Instruction *, 4> IncompleteRets;
3804 for (auto &I : llvm::reverse(instructions(F))) {
3805 auto It = ToProcess.find(&I);
3806 if (It == ToProcess.end())
3807 continue;
3808 It->second.remove_if([this](Value *V) { return !isTodoType(V); });
3809 if (It->second.size() == 0)
3810 continue;
3811 deduceOperandElementType(&I, &IncompleteRets, &It->second, true);
3812 if (TodoTypeSz == 0)
3813 return true;
3814 }
3815 }
3816
3817 return SzTodo > TodoTypeSz;
3818}
3819
3820// Parse and store argument types of function declarations where needed.
3821void SPIRVEmitIntrinsics::parseFunDeclarations(Module &M) {
3822 for (auto &F : M) {
3823 if (!F.isDeclaration() || F.isIntrinsic())
3824 continue;
3825 // get the demangled name
3826 std::string DemangledName = getOclOrSpirvBuiltinDemangledName(F.getName());
3827 if (DemangledName.empty())
3828 continue;
3829 // allow only OpGroupAsyncCopy use case at the moment
3830 const SPIRVSubtarget &ST = TM.getSubtarget<SPIRVSubtarget>(F);
3831 auto [Grp, Opcode, ExtNo] = SPIRV::mapBuiltinToOpcode(
3832 DemangledName, ST.getPreferredInstructionSet());
3833 if (Opcode != SPIRV::OpGroupAsyncCopy)
3834 continue;
3835 // find pointer arguments
3836 SmallVector<unsigned> Idxs;
3837 for (unsigned OpIdx = 0; OpIdx < F.arg_size(); ++OpIdx) {
3838 Argument *Arg = F.getArg(OpIdx);
3839 if (isPointerTy(Arg->getType()) && !hasPointeeTypeAttr(Arg))
3840 Idxs.push_back(OpIdx);
3841 }
3842 if (!Idxs.size())
3843 continue;
3844 // parse function arguments
3845 LLVMContext &Ctx = F.getContext();
3847 SPIRV::parseBuiltinTypeStr(TypeStrs, DemangledName, Ctx);
3848 if (!TypeStrs.size())
3849 continue;
3850 // find type info for pointer arguments
3851 for (unsigned Idx : Idxs) {
3852 if (Idx >= TypeStrs.size())
3853 continue;
3854 if (Type *ElemTy =
3855 SPIRV::parseBuiltinCallArgumentType(TypeStrs[Idx].trim(), Ctx))
3857 !ElemTy->isTargetExtTy())
3858 FDeclPtrTys[&F].push_back(std::make_pair(Idx, ElemTy));
3859 }
3860 }
3861}
3862
3863bool SPIRVEmitIntrinsics::processMaskedMemIntrinsic(IntrinsicInst &I) {
3864 const SPIRVSubtarget &ST = TM.getSubtarget<SPIRVSubtarget>(*I.getFunction());
3865
3866 if (I.getIntrinsicID() == Intrinsic::masked_gather) {
3867 if (!ST.canUseExtension(
3868 SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
3869 I.getContext().emitError(
3870 &I, "llvm.masked.gather requires SPV_INTEL_masked_gather_scatter "
3871 "extension");
3872 // Replace with poison to allow compilation to continue and report error.
3873 I.replaceAllUsesWith(PoisonValue::get(I.getType()));
3874 I.eraseFromParent();
3875 return true;
3876 }
3877
3878 IRBuilder<> B(&I);
3879
3880 Value *Ptrs = I.getArgOperand(0);
3881 Value *Mask = I.getArgOperand(1);
3882 Value *Passthru = I.getArgOperand(2);
3883
3884 // Alignment is stored as a parameter attribute, not as a regular parameter.
3885 uint32_t Alignment = I.getParamAlign(0).valueOrOne().value();
3886
3887 SmallVector<Value *, 4> Args = {Ptrs, B.getInt32(Alignment), Mask,
3888 Passthru};
3889 SmallVector<Type *, 4> Types = {I.getType(), Ptrs->getType(),
3890 Mask->getType(), Passthru->getType()};
3891
3892 auto *NewI = B.CreateIntrinsic(Intrinsic::spv_masked_gather, Types, Args);
3893 I.replaceAllUsesWith(NewI);
3894 I.eraseFromParent();
3895 return true;
3896 }
3897
3898 if (I.getIntrinsicID() == Intrinsic::masked_scatter) {
3899 if (!ST.canUseExtension(
3900 SPIRV::Extension::SPV_INTEL_masked_gather_scatter)) {
3901 I.getContext().emitError(
3902 &I, "llvm.masked.scatter requires SPV_INTEL_masked_gather_scatter "
3903 "extension");
3904 // Erase the intrinsic to allow compilation to continue and report error.
3905 I.eraseFromParent();
3906 return true;
3907 }
3908
3909 IRBuilder<> B(&I);
3910
3911 Value *Values = I.getArgOperand(0);
3912 Value *Ptrs = I.getArgOperand(1);
3913 Value *Mask = I.getArgOperand(2);
3914
3915 // Alignment is stored as a parameter attribute on the ptrs parameter (arg
3916 // 1).
3917 uint32_t Alignment = I.getParamAlign(1).valueOrOne().value();
3918
3919 SmallVector<Value *, 4> Args = {Values, Ptrs, B.getInt32(Alignment), Mask};
3920 SmallVector<Type *, 3> Types = {Values->getType(), Ptrs->getType(),
3921 Mask->getType()};
3922
3923 B.CreateIntrinsic(Intrinsic::spv_masked_scatter, Types, Args);
3924 I.eraseFromParent();
3925 return true;
3926 }
3927
3928 return false;
3929}
3930
3931// SPIR-V doesn't support bitcasts involving vector boolean type. Decompose such
3932// bitcasts into element-wise operations before building instructions
3933// worklist, so new instructions are properly visited and converted to
3934// SPIR-V intrinsics.
3935void SPIRVEmitIntrinsics::preprocessBoolVectorBitcasts(Function &F) {
3936 struct BoolVecBitcast {
3937 BitCastInst *BC;
3938 FixedVectorType *BoolVecTy;
3939 bool SrcIsBoolVec;
3940 };
3941
3942 auto getAsBoolVec = [](Type *Ty) -> FixedVectorType * {
3943 auto *VTy = dyn_cast<FixedVectorType>(Ty);
3944 return (VTy && VTy->getElementType()->isIntegerTy(1)) ? VTy : nullptr;
3945 };
3946
3948 for (auto &I : instructions(F)) {
3949 auto *BC = dyn_cast<BitCastInst>(&I);
3950 if (!BC)
3951 continue;
3952 if (auto *BVTy = getAsBoolVec(BC->getSrcTy()))
3953 ToReplace.push_back({BC, BVTy, true});
3954 else if (auto *BVTy = getAsBoolVec(BC->getDestTy()))
3955 ToReplace.push_back({BC, BVTy, false});
3956 }
3957
3958 for (auto &[BC, BoolVecTy, SrcIsBoolVec] : ToReplace) {
3959 IRBuilder<> B(BC);
3960 Value *Src = BC->getOperand(0);
3961 unsigned BoolVecN = BoolVecTy->getNumElements();
3962 // Use iN as the scalar intermediate type for the bool vector side.
3963 Type *IntTy = B.getIntNTy(BoolVecN);
3964
3965 // Convert source to scalar integer.
3966 Value *IntVal;
3967 if (SrcIsBoolVec) {
3968 // Extract each bool, zext, shift, and OR.
3969 IntVal = ConstantInt::get(IntTy, 0);
3970 for (unsigned I = 0; I < BoolVecN; ++I) {
3971 Value *Elem = B.CreateExtractElement(Src, B.getInt32(I));
3972 Value *Ext = B.CreateZExt(Elem, IntTy);
3973 if (I > 0)
3974 Ext = B.CreateShl(Ext, ConstantInt::get(IntTy, I));
3975 IntVal = B.CreateOr(IntVal, Ext);
3976 }
3977 } else {
3978 // Source is a non-bool type. If it's already a scalar integer, use it
3979 // directly, otherwise bitcast to iN first.
3980 IntVal = Src;
3981 if (!Src->getType()->isIntegerTy())
3982 IntVal = B.CreateBitCast(Src, IntTy);
3983 }
3984
3985 // Convert scalar integer to destination type.
3986 Value *Result;
3987 if (!SrcIsBoolVec) {
3988 // Test each bit with AND + icmp.
3989 Result = PoisonValue::get(BoolVecTy);
3990 for (unsigned I = 0; I < BoolVecN; ++I) {
3991 Value *Mask = ConstantInt::get(IntTy, APInt::getOneBitSet(BoolVecN, I));
3992 Value *And = B.CreateAnd(IntVal, Mask);
3993 Value *Cmp = B.CreateICmpNE(And, ConstantInt::get(IntTy, 0));
3994 Result = B.CreateInsertElement(Result, Cmp, B.getInt32(I));
3995 }
3996 } else {
3997 // Destination is a non-bool type. If it's a scalar integer, use IntVal
3998 // directly, otherwise bitcast from iN.
3999 Result = IntVal;
4000 if (!BC->getDestTy()->isIntegerTy())
4001 Result = B.CreateBitCast(IntVal, BC->getDestTy());
4002 }
4003
4004 BC->replaceAllUsesWith(Result);
4005 BC->eraseFromParent();
4006 }
4007}
4008
4009bool SPIRVEmitIntrinsics::convertMaskedMemIntrinsics(Module &M) {
4010 bool Changed = false;
4011
4012 for (Function &F : make_early_inc_range(M)) {
4013 if (!F.isIntrinsic())
4014 continue;
4015 Intrinsic::ID IID = F.getIntrinsicID();
4016 if (IID != Intrinsic::masked_gather && IID != Intrinsic::masked_scatter)
4017 continue;
4018
4019 for (User *U : make_early_inc_range(F.users())) {
4020 if (auto *II = dyn_cast<IntrinsicInst>(U))
4021 Changed |= processMaskedMemIntrinsic(*II);
4022 }
4023
4024 if (F.use_empty())
4025 F.eraseFromParent();
4026 }
4027
4028 return Changed;
4029}
4030
4031bool SPIRVEmitIntrinsics::runOnModule(Module &M) {
4032 bool Changed = false;
4033
4034 Changed |= convertMaskedMemIntrinsics(M);
4035
4036 parseFunDeclarations(M);
4037 insertConstantsForFPFastMathDefault(M);
4038 GVUsers.init(M);
4039
4040 TodoType.clear();
4041 for (auto &F : M)
4043
4044 // Specify function parameters after all functions were processed.
4045 for (auto &F : M) {
4046 // check if function parameter types are set
4047 CurrF = &F;
4048 if (!F.isDeclaration() && !F.isIntrinsic()) {
4049 IRBuilder<> B(F.getContext());
4050 processParamTypes(&F, B);
4051 }
4052 }
4053
4054 CanTodoType = false;
4055 Changed |= postprocessTypes(M);
4056
4057 if (HaveFunPtrs)
4058 Changed |= processFunctionPointers(M);
4059
4060 return Changed;
4061}
4062
4063PreservedAnalyses
4065 SPIRVEmitIntrinsics Legacy(TM);
4066 if (Legacy.runOnModule(M))
4067 return PreservedAnalyses::none();
4068 return PreservedAnalyses::all();
4069}
4070
4072 return new SPIRVEmitIntrinsics(TM);
4073}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
always inline
Expand Atomic instructions
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static void replaceAllUsesWith(Value *Old, Value *New, SmallPtrSet< BasicBlock *, 32 > &FreshBBs, bool IsHuge)
Replace all old uses with new ones, and push the updated BBs into FreshBBs.
static Type * getPointeeType(Value *Ptr, const DataLayout &DL)
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static bool runOnFunction(Function &F, bool PostInlining)
Hexagon Common GEP
iv Induction Variable Users
Definition IVUsers.cpp:48
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
#define T
MachineInstr unsigned OpIdx
uint64_t IntrinsicInst * II
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool isMemInstrToReplace(Instruction *I)
static bool isAggrConstForceInt32(const Value *V)
static SPIRV::FPFastMathDefaultInfoVector & getOrCreateFPFastMathDefaultInfoVec(const Module &M, DenseMap< Function *, SPIRV::FPFastMathDefaultInfoVector > &FPFastMathDefaultInfoMap, Function *F)
static Type * getAtomicElemTy(SPIRVGlobalRegistry *GR, Instruction *I, Value *PointerOperand)
static void reportFatalOnTokenType(const Instruction *I)
static void setInsertPointAfterDef(IRBuilder<> &B, Instruction *I)
static void emitAssignName(Instruction *I, IRBuilder<> &B)
static bool isArtificialGlobal(StringRef Name)
static Type * getPointeeTypeByCallInst(StringRef DemangledName, Function *CalledF, unsigned OpIdx)
static void createRoundingModeDecoration(Instruction *I, unsigned RoundingModeDeco, IRBuilder<> &B)
static void createDecorationIntrinsic(Instruction *I, MDNode *Node, IRBuilder<> &B)
static bool hasOnlyArtificialUses(const GlobalVariable &GV)
static bool isAggregateValueIdInstr(const Instruction &I)
static SPIRV::FPFastMathDefaultInfo & getFPFastMathDefaultInfo(SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec, const Type *Ty)
static bool isAbortCall(const Instruction &I, const SPIRVSubtarget &ST)
static cl::opt< bool > SpirvEmitOpNames("spirv-emit-op-names", cl::desc("Emit OpName for all instructions"), cl::init(false))
static bool tracesToPointerAlloca(Value *V)
static bool isUseListGlobal(StringRef Name)
static bool IsKernelArgInt8(Function *F, StoreInst *SI)
static void addSaturatedDecorationToIntrinsic(Instruction *I, IRBuilder<> &B)
static bool isFirstIndexZero(const GetElementPtrInst *GEP)
static void setInsertPointSkippingPhis(IRBuilder<> &B, Instruction *I)
static bool isSpvAggrPlaceholder(const Value *V)
static bool precededByAbortIntrinsic(const UnreachableInst &I, const SPIRVSubtarget &ST)
static FunctionType * getFunctionPointerElemType(Function *F, SPIRVGlobalRegistry *GR)
static bool isMultiRegisterAggregate(Value *V)
static void createSaturatedConversionDecoration(Instruction *I, IRBuilder<> &B)
static bool shouldEmitIntrinsicsForGlobalValue(const GlobalVariableUsers &GVUsers, const GlobalVariable &GV, const Function *F)
static Type * restoreMutatedType(SPIRVGlobalRegistry *GR, Instruction *I, Type *Ty)
static bool requireAssignType(Instruction *I)
static void insertSpirvDecorations(MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder MIB)
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
This file defines the SmallPtrSet class.
StringSet - A set-like wrapper for the StringMap.
DEMANGLE_NAMESPACE_BEGIN bool starts_with(std::string_view self, char C) noexcept
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Definition APInt.h:240
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
const Function * getParent() const
Definition Argument.h:44
static unsigned getPointerOperandIndex()
static unsigned getPointerOperandIndex()
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
Definition BasicBlock.h:530
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
static LLVM_ABI BlockAddress * get(Function *F, BasicBlock *BB)
Return a BlockAddress for the specified function and basic block.
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This class represents a function call, abstracting a target machine's calling convention.
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:537
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI std::optional< RoundingMode > getRoundingMode() const
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:299
iterator end()
Definition DenseMap.h:141
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:284
Type * getParamType(unsigned i) const
Parameter type accessors.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
const DataLayout & getDataLayout() const
Get the data layout of the module this function belongs to.
Definition Function.cpp:357
iterator begin()
Definition Function.h:827
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition Function.h:251
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
size_t arg_size() const
Definition Function.h:875
Type * getReturnType() const
Returns the type of the ret val.
Definition Function.h:216
Argument * getArg(unsigned i) const
Definition Function.h:860
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
static LLVM_ABI Type * getTypeAtIndex(Type *Ty, Value *Idx)
Return the type of the element at the given index of an indexable type.
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static unsigned getPointerOperandIndex()
PointerType * getType() const
Global values are always pointers.
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2893
LLVM_ABI void addDestination(BasicBlock *Dest)
Add a destination.
Base class for instruction visitors.
Definition InstVisitor.h:78
LLVM_ABI bool isDebugOrPseudoInst() const LLVM_READONLY
Return true if the instruction is a DbgInfoIntrinsic or PseudoProbeInst.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Instruction * user_back()
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
static unsigned getPointerOperandIndex()
Metadata node.
Definition Metadata.h:1069
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1426
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1565
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1432
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:614
Flags
Flags values. These may be or'd together.
static LLVM_ABI MetadataAsValue * get(LLVMContext &Context, Metadata *MD)
Definition Metadata.cpp:110
Metadata * getMetadata() const
Definition Metadata.h:202
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI)
void buildAssignPtr(IRBuilder<> &B, Type *ElemTy, Value *Arg)
Type * findDeducedCompositeType(const Value *Val)
void replaceAllUsesWith(Value *Old, Value *New, bool DeleteOld=true)
void addDeducedElementType(Value *Val, Type *Ty)
void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy)
Type * findMutated(const Value *Val)
void addDeducedCompositeType(Value *Val, Type *Ty)
void buildAssignType(IRBuilder<> &B, Type *Ty, Value *Arg)
Type * findDeducedElementType(const Value *Val)
void updateAssignType(CallInst *AssignCI, Value *Arg, Value *OfType)
CallInst * findAssignPtrTypeInstr(const Value *Val)
const SPIRVTargetLowering * getTargetLowering() const override
bool isLogicalSPIRV() const
bool canUseExtension(SPIRV::Extension::Extension E) const
const SPIRVSubtarget * getSubtargetImpl() const
iterator find(ConstPtrType Ptr) const
iterator end() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void assign(size_type NumElts, ValueParamT Elt)
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
static unsigned getPointerOperandIndex()
iterator end()
Definition StringMap.h:213
iterator find(StringRef Key)
Definition StringMap.h:226
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:683
static unsigned getPointerOperandIndex()
static LLVM_ABI TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})
Return a target extension type having the specified name and optional type and integer parameters.
Definition Type.cpp:972
const STC & getSubtarget(const Function &F) const
This method returns a pointer to the specified type of TargetSubtargetInfo.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:288
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition Type.h:279
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
Type * getArrayElementType() const
Definition Type.h:425
LLVM_ABI StringRef getTargetExtName() const
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:276
bool isTargetExtTy() const
Return true if this is a target extension type.
Definition Type.h:205
bool isAggregateType() const
Return true if the type is an aggregate type.
Definition Type.h:319
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
static LLVM_ABI Type * getDoubleTy(LLVMContext &C)
Definition Type.cpp:287
Type * getContainedType(unsigned i) const
This method is used to implement the type iterator (defined at the end of the file).
Definition Type.h:397
static LLVM_ABI Type * getFloatTy(LLVMContext &C)
Definition Type.cpp:286
static LLVM_ABI Type * getHalfTy(LLVMContext &C)
Definition Type.cpp:284
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
static LLVM_ABI bool isValidElementType(Type *ElemTy)
Return true if the specified type is valid as a element type.
static LLVM_ABI TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
This function has undefined behavior.
op_range operands()
Definition User.h:267
void setOperand(unsigned i, Value *Val)
Definition User.h:212
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition User.cpp:25
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
user_iterator user_begin()
Definition Value.h:402
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
iterator_range< user_iterator > users()
Definition Value.h:426
user_iterator user_end()
Definition Value.h:410
iterator_range< use_iterator > uses()
Definition Value.h:380
void mutateType(Type *Ty)
Mutate the type of this Value to be of the specified type.
Definition Value.h:807
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
bool user_empty() const
Definition Value.h:389
const ParentTy * getParent() const
Definition ilist_node.h:34
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ Entry
Definition COFF.h:862
@ SPIR_KERNEL
Used for SPIR kernel functions.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
bool match(Val *V, const Pattern &P)
auto m_Value()
Match an arbitrary value and ignore it.
auto m_AnyIntrinsic()
Matches any intrinsic call and ignore it.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:50
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:392
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:383
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:395
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
unsigned getNumElements(Type *Ty)
Definition SLPUtils.cpp:46
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:573
ModulePass * createSPIRVEmitIntrinsicsPass(const SPIRVTargetMachine &TM)
bool isTypedPointerWrapper(const TargetExtType *ExtTy)
Definition SPIRVUtils.h:415
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
unsigned getPointerAddressSpace(const Type *T)
Definition SPIRVUtils.h:386
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
CallInst * buildIntrWithMD(Intrinsic::ID IntrID, ArrayRef< Type * > Types, Value *Arg, Value *Arg2, ArrayRef< Constant * > Imms, IRBuilder<> &B)
bool isUntypedPointerVectorTy(const Type *T)
Definition SPIRVUtils.h:379
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
FPDecorationId
Definition SPIRVUtils.h:559
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
bool isNestedPointer(const Type *Ty)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
Function * getOrCreateBackendServiceFunction(Module &M)
MetadataAsValue * buildMD(Value *Arg)
Definition SPIRVUtils.h:525
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
SmallVector< unsigned, 1 > getSpirvLoopControlOperandsFromLoopMetadata(MDNode *LoopMD)
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
Type * getTypedPointerWrapper(Type *ElemTy, unsigned AS)
Definition SPIRVUtils.h:410
bool isVector1(Type *Ty)
Definition SPIRVUtils.h:503
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isPointerTy(const Type *T)
Definition SPIRVUtils.h:374
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id)
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
Type * getPointeeTypeByAttr(Argument *Arg)
Definition SPIRVUtils.h:399
bool hasPointeeTypeAttr(Argument *Arg)
Definition SPIRVUtils.h:394
constexpr unsigned BitWidth
bool isEquivalentTypes(Type *Ty1, Type *Ty2)
Definition SPIRVUtils.h:465
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
bool hasInitializer(const GlobalVariable *GV)
Definition SPIRVUtils.h:355
Type * normalizeType(Type *Ty)
Definition SPIRVUtils.h:511
bool isPointerTyOrWrapper(const Type *Ty)
Definition SPIRVUtils.h:422
@ Enabled
Convert any .debug_str_offsets tables to DWARF64 if needed.
Definition DWP.h:31
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
PoisonValue * getNormalizedPoisonValue(Type *Ty)
Definition SPIRVUtils.h:521
bool isUntypedPointerTy(const Type *T)
Definition SPIRVUtils.h:369
Type * reconstitutePeeledArrayType(Type *Ty)
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
#define N
static size_t computeFPFastMathDefaultInfoVecIndex(size_t BitWidth)
Definition SPIRVUtils.h:149