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