1//===--- SPIRVUtils.h ---- SPIR-V Utility Functions -------------*- C++ -*-===// 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 7//===----------------------------------------------------------------------===// 9// This file contains miscellaneous utility functions. 11//===----------------------------------------------------------------------===// 13#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H 14#define LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H 25#include <unordered_map> 26#include <unordered_set> 32classMachineInstrBuilder;
34classMachineRegisterInfo;
39classSPIRVGlobalRegistry;
41// This class implements a partial ordering visitor, which visits a cyclic graph 42// in natural topological-like ordering. Topological ordering is not defined for 43// directed graphs with cycles, so this assumes cycles are a single node, and 44// ignores back-edges. The cycle is visited from the entry in the same 45// topological-like ordering. 47// Note: this visitor REQUIRES a reducible graph. 49// This means once we visit a node, we know all the possible ancestors have been 57// A -+ +---> D ----> E -> F -> G -> H 62// A, [B, C in any order], D, E, F, G, H 66// Changing the function CFG between the construction of the visitor and 67// visiting is undefined. The visitor can be reused, but if the CFG is updated, 68// the visitor must be rebuilt. 73 std::unordered_set<BasicBlock *> Queued = {};
74 std::queue<BasicBlock *> ToVisit = {};
81usingBlockToOrderInfoMap = std::unordered_map<BasicBlock *, OrderInfo>;
82 BlockToOrderInfoMap BlockToOrder;
83 std::vector<BasicBlock *> Order = {};
85// Get all basic-blocks reachable from Start. 86 std::unordered_set<BasicBlock *> getReachableFrom(
BasicBlock *Start);
88// Internal function used to determine the partial ordering. 89// Visits |BB| with the current rank being |Rank|. 97// Build the visitor to operate on the function F. 100// Returns true is |LHS| comes before |RHS| in the partial ordering. 101// If |LHS| and |RHS| have the same rank, the traversal order determines the 102// order (order is stable). 105// Visit the function starting from the basic block |Start|, and calling |Op| 106// on each visited BB. This traversal ignores back-edges, meaning this won't 107// visit a node to which |Start| is not an ancestor. 108// If Op returns |true|, the visitor continues. If |Op| returns false, the 109// visitor will stop at that rank. This means if 2 nodes share the same rank, 110// and Op returns false when visiting the first, the second will be visited 111// afterwards. But none of their successors will. 116// Add the given string as a series of integer operand, inserting null 117// terminators and padding to make sure the operands all have 32-bit 118// little-endian words. 122 std::vector<Value *> &Args);
124// Read the series of integer operands back as a null-terminated string using 125// the reverse of the logic in addStringImm. 128// Add the given numerical immediate to MIB. 131// Add an OpName instruction for the given target register. 137// Add an OpDecorate instruction for the given Reg. 139 SPIRV::Decoration::Decoration Dec,
140const std::vector<uint32_t> &DecArgs,
143 SPIRV::Decoration::Decoration Dec,
144const std::vector<uint32_t> &DecArgs,
147// Add an OpDecorate instruction by "spirv.Decorations" metadata node. 151// Return a valid position for the OpVariable instruction inside a function, 152// i.e., at the beginning of the first block of the function. 155// Return a valid position for the instruction at the end of the block before 156// terminators and debug instructions. 159// Convert a SPIR-V storage class to the corresponding LLVM IR address space. 160// TODO: maybe the following two functions should be handled in the subtarget 161// to allow for different OpenCL vs Vulkan handling. 165case SPIRV::StorageClass::Function:
167case SPIRV::StorageClass::CrossWorkgroup:
169case SPIRV::StorageClass::UniformConstant:
171case SPIRV::StorageClass::Workgroup:
173case SPIRV::StorageClass::Generic:
175case SPIRV::StorageClass::DeviceOnlyINTEL:
177case SPIRV::StorageClass::HostOnlyINTEL:
179case SPIRV::StorageClass::Input:
181case SPIRV::StorageClass::Output:
183case SPIRV::StorageClass::CodeSectionINTEL:
185case SPIRV::StorageClass::Private:
192// Convert an LLVM IR address space to a SPIR-V storage class. 193SPIRV::StorageClass::StorageClass
196SPIRV::MemorySemantics::MemorySemantics
203// Find def instruction for the given ConstReg, walking through 204// spv_track_constant and ASSIGN_TYPE instructions. Updates ConstReg by def 205// of OpConstant instruction. 207const MachineRegisterInfo *
MRI);
209// Get constant integer value of the given ConstReg. 212// Check if MI is a SPIR-V specific intrinsic call. 214// Check if it's a SPIR-V specific intrinsic call. 217// Get type of i-th operand of the metadata node. 220// If OpenCL or SPIR-V builtin function name is recognized, return a demangled 221// name, otherwise return an empty string. 224// Check if a string contains a builtin prefix. 227// Check if given LLVM type is a special opaque builtin type. 230// Check if the function is an SPIR-V entry point 233// Parse basic scalar type name, substring TypeName, and return LLVM type. 236// Sort blocks in a partial ordering, so each block is after all its 237// dominators. This should match both the SPIR-V and the MIR requirements. 238// Returns true if the function was changed. 245// True if this is an instance of TypedPointerType. 250// True if this is an instance of PointerType. 255// True if this is an instance of PointerType or TypedPointerType. 260// Get the address space of this pointer or pointer vector type for instances of 261// PointerType or TypedPointerType. 263Type *SubT =
T->getScalarType();
265 ? cast<PointerType>(SubT)->getAddressSpace()
266 : cast<TypedPointerType>(SubT)->getAddressSpace();
269// Return true if the Argument is decorated with a pointee type 274// Return the pointee type of the argument or nullptr otherwise 287for (
unsigned i = 0; i <
F->arg_size(); ++i)
292#define TYPED_PTR_TARGET_EXT_NAME "spirv.$TypedPointerType" 304// True if this is an instance of PointerType or TypedPointerType. 306if (
auto *ExtTy = dyn_cast<TargetExtType>(Ty))
312if (
auto *ExtTy = dyn_cast<TargetExtType>(Ty)) {
315 ExtTy->getIntParameter(0));
316 }
elseif (
auto *VecTy = dyn_cast<VectorType>(Ty)) {
317Type *ElemTy = VecTy->getElementType();
319if (NewElemTy != ElemTy)
327if (
auto PType = dyn_cast<TypedPointerType>(Ty))
328return PType->getElementType();
329elseif (
auto *ExtTy = dyn_cast<TargetExtType>(Ty))
331return ExtTy->getTypeParameter(0);
339if (
auto *ExtTy = dyn_cast<TargetExtType>(Ty2))
341 ExtTy->getTypeParameter(0) ==
343 ExtTy->getIntParameter(0) == cast<PointerType>(Ty1)->getAddressSpace())
365bool IsUntypedPtr =
false;
372if (!IsUntypedPtr &&
RetTy == OrigRetTy)
381if (
auto FTy = dyn_cast<FunctionType>(Ty))
388#define SPIRV_BACKEND_SERVICE_FUN_NAME "__spirv_backend_service_fun" 392 MachineIRBuilder &MIRBuilder,
bool Force =
false);
406// Return true if there is an opaque pointer type nested in the argument. 412static std::unordered_map<std::string, FPDecorationId> Mapping = {
418auto It = Mapping.find(S);
423#endif// LLVM_LIB_TARGET_SPIRV_SPIRVUTILS_H unsigned const MachineRegisterInfo * MRI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
Promote Memory to Register
#define TYPED_PTR_TARGET_EXT_NAME
Class for arbitrary precision integers.
This class represents an incoming formal argument to a Function.
Type * getParamByRefType() const
If this is a byref argument, return its type.
bool hasByRefAttr() const
Return true if this argument has the byref attribute.
Type * getParamStructRetType() const
If this is an sret argument, return its type.
bool hasByValAttr() const
Return true if this argument has the byval attribute.
Type * getParamByValType() const
If this is a byval argument, return its type.
bool hasStructRetAttr() const
Return true if this argument has the sret attribute.
LLVM Basic Block Representation.
This class represents an Operation in the Expression.
Core dominator tree base class.
Class to represent function types.
ArrayRef< Type * > params() const
Type * getReturnType() const
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Instances of this class represent a single low-level machine instruction.
Helper class to build MachineInstr.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
size_t GetNodeRank(BasicBlock *BB) const
void partialOrderVisit(BasicBlock &Start, std::function< bool(BasicBlock *)> Op)
bool compare(const BasicBlock *LHS, const BasicBlock *RHS) const
Wrapper class representing virtual and physical registers.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Class to represent target extensions types, which are generally unintrospectable from target-independ...
unsigned getNumIntParameters() const
static 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.
unsigned getNumTypeParameters() const
StringRef getName() const
Return the name for this target extension type.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
@ TypedPointerTyID
Typed pointer used by some GPU targets.
bool isTargetExtTy() const
Return true if this is a target extension type.
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
static IntegerType * getInt8Ty(LLVMContext &C)
TypeID getTypeID() const
Return the type id for the type.
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.
This is an optimization pass for GlobalISel generic memory operations.
void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)
bool getVacantFunctionName(Module &M, std::string &Name)
std::string getStringImm(const MachineInstr &MI, unsigned StartIndex)
bool isTypedPointerWrapper(const TargetExtType *ExtTy)
unsigned getPointerAddressSpace(const Type *T)
void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)
FPDecorationId demangledPostfixToDecorationId(const std::string &S)
bool sortBlocks(Function &F)
Type * toTypedFunPointer(FunctionType *FTy)
uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)
SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)
constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)
bool isNestedPointer(const Type *Ty)
std::string getOclOrSpirvBuiltinDemangledName(StringRef Name)
bool isTypedPointerTy(const Type *T)
bool isUntypedEquivalentToTyExt(Type *Ty1, Type *Ty2)
void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)
MachineBasicBlock::iterator getOpVariableMBBIt(MachineInstr &I)
Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
Type * getTypedPointerWrapper(Type *ElemTy, unsigned AS)
Type * reconstructFunctionType(Function *F)
Type * toTypedPointer(Type *Ty)
bool isSpecialOpaqueType(const Type *Ty)
void setRegClassType(Register Reg, SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)
bool isPointerTy(const Type *T)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
MachineBasicBlock::iterator getInsertPtValidEnd(MachineBasicBlock *MBB)
const Type * unifyPtrType(const Type *Ty)
bool isEntryPoint(const Function &F)
SPIRV::StorageClass::StorageClass addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI)
AtomicOrdering
Atomic ordering for LLVM's memory model.
SPIRV::Scope::Scope getMemScope(LLVMContext &Ctx, SyncScope::ID Id)
Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)
Type * getPointeeTypeByAttr(Argument *Arg)
bool hasPointeeTypeAttr(Argument *Arg)
MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)
bool isEquivalentTypes(Type *Ty1, Type *Ty2)
bool hasBuiltinTypePrefix(StringRef Name)
Type * getMDOperandAsType(const MDNode *N, unsigned I)
bool hasInitializer(const GlobalVariable *GV)
Type * applyWrappers(Type *Ty)
bool isPointerTyOrWrapper(const Type *Ty)
bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)
Type * getPointeeType(const Type *Ty)
void addStringImm(const StringRef &Str, MCInst &Inst)
MachineInstr * getVRegDef(MachineRegisterInfo &MRI, Register Reg)
void buildOpSpirvDecorations(Register Reg, MachineIRBuilder &MIRBuilder, const MDNode *GVarMD)
bool isUntypedPointerTy(const Type *T)
SPIRV::MemorySemantics::MemorySemantics getMemSemantics(AtomicOrdering Ord)