LLVM 20.0.0git
SPIRVUtils.h
Go to the documentation of this file.
1//===--- SPIRVUtils.h ---- SPIR-V Utility Functions -------------*- 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// This file contains miscellaneous utility functions.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
14#define LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
15
17#include "llvm/IR/IRBuilder.h"
19#include <string>
20
21namespace llvm {
22class MCInst;
23class MachineFunction;
24class MachineInstr;
25class MachineInstrBuilder;
26class MachineIRBuilder;
27class MachineRegisterInfo;
28class Register;
29class StringRef;
30class SPIRVInstrInfo;
31class SPIRVSubtarget;
32
33// Add the given string as a series of integer operand, inserting null
34// terminators and padding to make sure the operands all have 32-bit
35// little-endian words.
36void addStringImm(const StringRef &Str, MCInst &Inst);
37void addStringImm(const StringRef &Str, MachineInstrBuilder &MIB);
38void addStringImm(const StringRef &Str, IRBuilder<> &B,
39 std::vector<Value *> &Args);
40
41// Read the series of integer operands back as a null-terminated string using
42// the reverse of the logic in addStringImm.
43std::string getStringImm(const MachineInstr &MI, unsigned StartIndex);
44
45// Add the given numerical immediate to MIB.
46void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB);
47
48// Add an OpName instruction for the given target register.
49void buildOpName(Register Target, const StringRef &Name,
50 MachineIRBuilder &MIRBuilder);
51
52// Add an OpDecorate instruction for the given Reg.
53void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder,
54 SPIRV::Decoration::Decoration Dec,
55 const std::vector<uint32_t> &DecArgs,
56 StringRef StrImm = "");
57void buildOpDecorate(Register Reg, MachineInstr &I, const SPIRVInstrInfo &TII,
58 SPIRV::Decoration::Decoration Dec,
59 const std::vector<uint32_t> &DecArgs,
60 StringRef StrImm = "");
61
62// Add an OpDecorate instruction by "spirv.Decorations" metadata node.
63void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder,
64 const MDNode *GVarMD);
65
66// Convert a SPIR-V storage class to the corresponding LLVM IR address space.
67unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC);
68
69// Convert an LLVM IR address space to a SPIR-V storage class.
70SPIRV::StorageClass::StorageClass
71addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI);
72
73SPIRV::MemorySemantics::MemorySemantics
74getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC);
75
76SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord);
77
78// Find def instruction for the given ConstReg, walking through
79// spv_track_constant and ASSIGN_TYPE instructions. Updates ConstReg by def
80// of OpConstant instruction.
81MachineInstr *getDefInstrMaybeConstant(Register &ConstReg,
82 const MachineRegisterInfo *MRI);
83
84// Get constant integer value of the given ConstReg.
85uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI);
86
87// Check if MI is a SPIR-V specific intrinsic call.
88bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID);
89
90// Get type of i-th operand of the metadata node.
91Type *getMDOperandAsType(const MDNode *N, unsigned I);
92
93// If OpenCL or SPIR-V builtin function name is recognized, return a demangled
94// name, otherwise return an empty string.
95std::string getOclOrSpirvBuiltinDemangledName(StringRef Name);
96
97// Check if a string contains a builtin prefix.
98bool hasBuiltinTypePrefix(StringRef Name);
99
100// Check if given LLVM type is a special opaque builtin type.
101bool isSpecialOpaqueType(const Type *Ty);
102
103// Check if the function is an SPIR-V entry point
104bool isEntryPoint(const Function &F);
105
106// Parse basic scalar type name, substring TypeName, and return LLVM type.
107Type *parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx);
108
109// True if this is an instance of TypedPointerType.
110inline bool isTypedPointerTy(const Type *T) {
111 return T && T->getTypeID() == Type::TypedPointerTyID;
112}
113
114// True if this is an instance of PointerType.
115inline bool isUntypedPointerTy(const Type *T) {
116 return T && T->getTypeID() == Type::PointerTyID;
117}
118
119// True if this is an instance of PointerType or TypedPointerType.
120inline bool isPointerTy(const Type *T) {
122}
123
124// Get the address space of this pointer or pointer vector type for instances of
125// PointerType or TypedPointerType.
126inline unsigned getPointerAddressSpace(const Type *T) {
127 Type *SubT = T->getScalarType();
128 return SubT->getTypeID() == Type::PointerTyID
129 ? cast<PointerType>(SubT)->getAddressSpace()
130 : cast<TypedPointerType>(SubT)->getAddressSpace();
131}
132
133// Return true if the Argument is decorated with a pointee type
134inline bool hasPointeeTypeAttr(Argument *Arg) {
135 return Arg->hasByValAttr() || Arg->hasByRefAttr() || Arg->hasStructRetAttr();
136}
137
138// Return the pointee type of the argument or nullptr otherwise
140 if (Arg->hasByValAttr())
141 return Arg->getParamByValType();
142 if (Arg->hasStructRetAttr())
143 return Arg->getParamStructRetType();
144 if (Arg->hasByRefAttr())
145 return Arg->getParamByRefType();
146 return nullptr;
147}
148
150 SmallVector<Type *> ArgTys;
151 for (unsigned i = 0; i < F->arg_size(); ++i)
152 ArgTys.push_back(F->getArg(i)->getType());
153 return FunctionType::get(F->getReturnType(), ArgTys, F->isVarArg());
154}
155
156#define TYPED_PTR_TARGET_EXT_NAME "spirv.$TypedPointerType"
157inline Type *getTypedPointerWrapper(Type *ElemTy, unsigned AS) {
159 {ElemTy}, {AS});
160}
161
163 return ExtTy->getName() == TYPED_PTR_TARGET_EXT_NAME &&
164 ExtTy->getNumIntParameters() == 1 &&
165 ExtTy->getNumTypeParameters() == 1;
166}
167
168inline Type *applyWrappers(Type *Ty) {
169 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty)) {
170 if (isTypedPointerWrapper(ExtTy))
171 return TypedPointerType::get(applyWrappers(ExtTy->getTypeParameter(0)),
172 ExtTy->getIntParameter(0));
173 } else if (auto *VecTy = dyn_cast<VectorType>(Ty)) {
174 Type *ElemTy = VecTy->getElementType();
175 Type *NewElemTy = ElemTy->isTargetExtTy() ? applyWrappers(ElemTy) : ElemTy;
176 if (NewElemTy != ElemTy)
177 return VectorType::get(NewElemTy, VecTy->getElementCount());
178 }
179 return Ty;
180}
181
183 if (auto PType = dyn_cast<TypedPointerType>(Ty))
184 return PType->getElementType();
185 else if (auto *ExtTy = dyn_cast<TargetExtType>(Ty))
186 if (isTypedPointerWrapper(ExtTy))
187 return applyWrappers(ExtTy->getTypeParameter(0));
188 return nullptr;
189}
190
191inline bool isUntypedEquivalentToTyExt(Type *Ty1, Type *Ty2) {
192 if (!isUntypedPointerTy(Ty1) || !Ty2)
193 return false;
194 if (auto *ExtTy = dyn_cast<TargetExtType>(Ty2))
195 if (isTypedPointerWrapper(ExtTy) &&
196 ExtTy->getTypeParameter(0) ==
198 ExtTy->getIntParameter(0) == cast<PointerType>(Ty1)->getAddressSpace())
199 return true;
200 return false;
201}
202
203inline bool isEquivalentTypes(Type *Ty1, Type *Ty2) {
204 return isUntypedEquivalentToTyExt(Ty1, Ty2) ||
206}
207
209 if (Type *NewTy = applyWrappers(Ty); NewTy != Ty)
210 return NewTy;
211 return isUntypedPointerTy(Ty)
214 : Ty;
215}
216
218 Type *OrigRetTy = FTy->getReturnType();
219 Type *RetTy = toTypedPointer(OrigRetTy);
220 bool IsUntypedPtr = false;
221 for (Type *PTy : FTy->params()) {
222 if (isUntypedPointerTy(PTy)) {
223 IsUntypedPtr = true;
224 break;
225 }
226 }
227 if (!IsUntypedPtr && RetTy == OrigRetTy)
228 return FTy;
229 SmallVector<Type *> ParamTys;
230 for (Type *PTy : FTy->params())
231 ParamTys.push_back(toTypedPointer(PTy));
232 return FunctionType::get(RetTy, ParamTys, FTy->isVarArg());
233}
234
235inline const Type *unifyPtrType(const Type *Ty) {
236 if (auto FTy = dyn_cast<FunctionType>(Ty))
237 return toTypedFunPointer(const_cast<FunctionType *>(FTy));
238 return toTypedPointer(const_cast<Type *>(Ty));
239}
240
241} // namespace llvm
242#endif // LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H
unsigned const MachineRegisterInfo * MRI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
RelocType Type
Definition: COFFYAML.cpp:391
return RetTy
std::string Name
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned Reg
Promote Memory to Register
Definition: Mem2Reg.cpp:110
#define TYPED_PTR_TARGET_EXT_NAME
Definition: SPIRVUtils.h:156
This class represents an incoming formal argument to a Function.
Definition: Argument.h:31
Type * getParamByRefType() const
If this is a byref argument, return its type.
Definition: Function.cpp:264
bool hasByRefAttr() const
Return true if this argument has the byref attribute.
Definition: Function.cpp:168
Type * getParamStructRetType() const
If this is an sret argument, return its type.
Definition: Function.cpp:259
bool hasByValAttr() const
Return true if this argument has the byval attribute.
Definition: Function.cpp:163
Type * getParamByValType() const
If this is a byval argument, return its type.
Definition: Function.cpp:254
bool hasStructRetAttr() const
Return true if this argument has the sret attribute.
Definition: Function.cpp:317
Class to represent function types.
Definition: DerivedTypes.h:103
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:130
bool isVarArg() const
Definition: DerivedTypes.h:123
Type * getReturnType() const
Definition: DerivedTypes.h:124
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
void push_back(const T &Elt)
Definition: SmallVector.h:427
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1210
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Definition: DerivedTypes.h:720
unsigned getNumIntParameters() const
Definition: DerivedTypes.h:765
static TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types=std::nullopt, ArrayRef< unsigned > Ints=std::nullopt)
Return a target extension type having the specified name and optional type and integer parameters.
Definition: Type.cpp:784
unsigned getNumTypeParameters() const
Definition: DerivedTypes.h:756
StringRef getName() const
Return the name for this target extension type.
Definition: DerivedTypes.h:741
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
@ TypedPointerTyID
Typed pointer used by some GPU targets.
Definition: Type.h:77
@ PointerTyID
Pointers.
Definition: Type.h:72
bool isTargetExtTy() const
Return true if this is a target extension type.
Definition: Type.h:203
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:128
static IntegerType * getInt8Ty(LLVMContext &C)
TypeID getTypeID() const
Return the type id for the type.
Definition: Type.h:136
static TypedPointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
Definition: Type.cpp:664
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
Definition: SPIRVUtils.cpp:100
unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.cpp:166
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
Definition: SPIRVUtils.cpp:76
unsigned getPointerAddressSpace(const Type *T)
Definition: SPIRVUtils.h:126
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
Definition: SPIRVUtils.cpp:80
Type * toTypedFunPointer(FunctionType *FTy)
Definition: SPIRVUtils.h:217
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:273
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
Definition: SPIRVUtils.cpp:218
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
Definition: SPIRVUtils.cpp:339
bool isTypedPointerTy(const Type *T)
Definition: SPIRVUtils.h:110
bool isUntypedEquivalentToTyExt(Type *Ty1, Type *Ty2)
Definition: SPIRVUtils.h:191
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
Definition: SPIRVUtils.cpp:117
Type * getTypedPointerWrapper(Type *ElemTy, unsigned AS)
Definition: SPIRVUtils.h:157
Type * reconstructFunctionType(Function *F)
Definition: SPIRVUtils.h:149
Type * toTypedPointer(Type *Ty)
Definition: SPIRVUtils.h:208
bool isSpecialOpaqueType(const Type *Ty)
Definition: SPIRVUtils.cpp:383
bool isPointerTy(const Type *T)
Definition: SPIRVUtils.h:120
const Type * unifyPtrType(const Type *Ty)
Definition: SPIRVUtils.h:235
bool isTypedPointerWrapper(TargetExtType *ExtTy)
Definition: SPIRVUtils.h:162
bool isEntryPoint(const Function &F)
Definition: SPIRVUtils.cpp:390
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
Definition: SPIRVUtils.cpp:190
AtomicOrdering
Atomic ordering for LLVM's memory model.
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
Definition: SPIRVUtils.cpp:404
Type * getPointeeTypeByAttr(Argument *Arg)
Definition: SPIRVUtils.h:139
bool hasPointeeTypeAttr(Argument *Arg)
Definition: SPIRVUtils.h:134
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
Definition: SPIRVUtils.cpp:254
bool isEquivalentTypes(Type *Ty1, Type *Ty2)
Definition: SPIRVUtils.h:203
bool hasBuiltinTypePrefix(StringRef Name)
Definition: SPIRVUtils.cpp:376
Type * getMDOperandAsType(const MDNode *N, unsigned I)
Definition: SPIRVUtils.cpp:285
Type * getPointeeType(Type *Ty)
Definition: SPIRVUtils.h:182
Type * applyWrappers(Type *Ty)
Definition: SPIRVUtils.h:168
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
Definition: SPIRVUtils.cpp:279
void addStringImm(const StringRef &Str, MCInst &Inst)
Definition: SPIRVUtils.cpp:51
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
Definition: SPIRVUtils.cpp:136
bool isUntypedPointerTy(const Type *T)
Definition: SPIRVUtils.h:115
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)
Definition: SPIRVUtils.cpp:236
#define N