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