Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
35269 views
//===-- SPIRVGlobalRegistry.h - SPIR-V Global Registry ----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// SPIRVGlobalRegistry is used to maintain rich type information required for9// SPIR-V even after lowering from LLVM IR to GMIR. It can convert an llvm::Type10// into an OpTypeXXX instruction, and map it to a virtual register. Also it11// builds and supports consistency of constants and global variables.12//13//===----------------------------------------------------------------------===//1415#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H16#define LLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H1718#include "MCTargetDesc/SPIRVBaseInfo.h"19#include "SPIRVDuplicatesTracker.h"20#include "SPIRVInstrInfo.h"21#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"22#include "llvm/IR/Constant.h"23#include "llvm/IR/TypedPointerType.h"2425namespace llvm {26class SPIRVSubtarget;27using SPIRVType = const MachineInstr;2829class SPIRVGlobalRegistry {30// Registers holding values which have types associated with them.31// Initialized upon VReg definition in IRTranslator.32// Do not confuse this with DuplicatesTracker as DT maps Type* to <MF, Reg>33// where Reg = OpType...34// while VRegToTypeMap tracks SPIR-V type assigned to other regs (i.e. not35// type-declaring ones).36DenseMap<const MachineFunction *, DenseMap<Register, SPIRVType *>>37VRegToTypeMap;3839// Map LLVM Type* to <MF, Reg>40SPIRVGeneralDuplicatesTracker DT;4142DenseMap<SPIRVType *, const Type *> SPIRVToLLVMType;4344// map a Function to its definition (as a machine instruction operand)45DenseMap<const Function *, const MachineOperand *> FunctionToInstr;46DenseMap<const MachineInstr *, const Function *> FunctionToInstrRev;47// map function pointer (as a machine instruction operand) to the used48// Function49DenseMap<const MachineOperand *, const Function *> InstrToFunction;50// Maps Functions to their calls (in a form of the machine instruction,51// OpFunctionCall) that happened before the definition is available52DenseMap<const Function *, SmallPtrSet<MachineInstr *, 8>> ForwardCalls;53// map a Function to its original return type before the clone function was54// created during substitution of aggregate arguments55// (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`)56DenseMap<Value *, Type *> MutatedAggRet;5758// Look for an equivalent of the newType in the map. Return the equivalent59// if it's found, otherwise insert newType to the map and return the type.60const MachineInstr *checkSpecialInstr(const SPIRV::SpecialTypeDescriptor &TD,61MachineIRBuilder &MIRBuilder);6263SmallPtrSet<const Type *, 4> TypesInProcessing;64DenseMap<const Type *, SPIRVType *> ForwardPointerTypes;6566// if a function returns a pointer, this is to map it into TypedPointerType67DenseMap<const Function *, TypedPointerType *> FunResPointerTypes;6869// Number of bits pointers and size_t integers require.70const unsigned PointerSize;7172// Holds the maximum ID we have in the module.73unsigned Bound;7475// Maps values associated with untyped pointers into deduced element types of76// untyped pointers.77DenseMap<Value *, Type *> DeducedElTys;78// Maps composite values to deduced types where untyped pointers are replaced79// with typed ones.80DenseMap<Value *, Type *> DeducedNestedTys;81// Maps values to "assign type" calls, thus being a registry of created82// Intrinsic::spv_assign_ptr_type instructions.83DenseMap<Value *, CallInst *> AssignPtrTypeInstr;8485// Add a new OpTypeXXX instruction without checking for duplicates.86SPIRVType *createSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,87SPIRV::AccessQualifier::AccessQualifier AQ =88SPIRV::AccessQualifier::ReadWrite,89bool EmitIR = true);90SPIRVType *findSPIRVType(const Type *Ty, MachineIRBuilder &MIRBuilder,91SPIRV::AccessQualifier::AccessQualifier accessQual =92SPIRV::AccessQualifier::ReadWrite,93bool EmitIR = true);94SPIRVType *95restOfCreateSPIRVType(const Type *Type, MachineIRBuilder &MIRBuilder,96SPIRV::AccessQualifier::AccessQualifier AccessQual,97bool EmitIR);9899public:100SPIRVGlobalRegistry(unsigned PointerSize);101102MachineFunction *CurMF;103104void add(const Constant *C, MachineFunction *MF, Register R) {105DT.add(C, MF, R);106}107108void add(const GlobalVariable *GV, MachineFunction *MF, Register R) {109DT.add(GV, MF, R);110}111112void add(const Function *F, MachineFunction *MF, Register R) {113DT.add(F, MF, R);114}115116void add(const Argument *Arg, MachineFunction *MF, Register R) {117DT.add(Arg, MF, R);118}119120void add(const MachineInstr *MI, MachineFunction *MF, Register R) {121DT.add(MI, MF, R);122}123124Register find(const MachineInstr *MI, MachineFunction *MF) {125return DT.find(MI, MF);126}127128Register find(const Constant *C, MachineFunction *MF) {129return DT.find(C, MF);130}131132Register find(const GlobalVariable *GV, MachineFunction *MF) {133return DT.find(GV, MF);134}135136Register find(const Function *F, MachineFunction *MF) {137return DT.find(F, MF);138}139140void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,141MachineModuleInfo *MMI = nullptr) {142DT.buildDepsGraph(Graph, MMI);143}144145void setBound(unsigned V) { Bound = V; }146unsigned getBound() { return Bound; }147148// Add a record to the map of function return pointer types.149void addReturnType(const Function *ArgF, TypedPointerType *DerivedTy) {150FunResPointerTypes[ArgF] = DerivedTy;151}152// Find a record in the map of function return pointer types.153const TypedPointerType *findReturnType(const Function *ArgF) {154auto It = FunResPointerTypes.find(ArgF);155return It == FunResPointerTypes.end() ? nullptr : It->second;156}157158// A registry of "assign type" records:159// - Add a record.160void addAssignPtrTypeInstr(Value *Val, CallInst *AssignPtrTyCI) {161AssignPtrTypeInstr[Val] = AssignPtrTyCI;162}163// - Find a record.164CallInst *findAssignPtrTypeInstr(const Value *Val) {165auto It = AssignPtrTypeInstr.find(Val);166return It == AssignPtrTypeInstr.end() ? nullptr : It->second;167}168169// A registry of mutated values170// (see `SPIRVPrepareFunctions::removeAggregateTypesFromSignature()`):171// - Add a record.172void addMutated(Value *Val, Type *Ty) { MutatedAggRet[Val] = Ty; }173// - Find a record.174Type *findMutated(const Value *Val) {175auto It = MutatedAggRet.find(Val);176return It == MutatedAggRet.end() ? nullptr : It->second;177}178179// Deduced element types of untyped pointers and composites:180// - Add a record to the map of deduced element types.181void addDeducedElementType(Value *Val, Type *Ty) { DeducedElTys[Val] = Ty; }182// - Find a record in the map of deduced element types.183Type *findDeducedElementType(const Value *Val) {184auto It = DeducedElTys.find(Val);185return It == DeducedElTys.end() ? nullptr : It->second;186}187// - Add a record to the map of deduced composite types.188void addDeducedCompositeType(Value *Val, Type *Ty) {189DeducedNestedTys[Val] = Ty;190}191// - Find a record in the map of deduced composite types.192Type *findDeducedCompositeType(const Value *Val) {193auto It = DeducedNestedTys.find(Val);194return It == DeducedNestedTys.end() ? nullptr : It->second;195}196// - Find a type of the given Global value197Type *getDeducedGlobalValueType(const GlobalValue *Global) {198// we may know element type if it was deduced earlier199Type *ElementTy = findDeducedElementType(Global);200if (!ElementTy) {201// or we may know element type if it's associated with a composite202// value203if (Value *GlobalElem =204Global->getNumOperands() > 0 ? Global->getOperand(0) : nullptr)205ElementTy = findDeducedCompositeType(GlobalElem);206}207return ElementTy ? ElementTy : Global->getValueType();208}209210// Map a machine operand that represents a use of a function via function211// pointer to a machine operand that represents the function definition.212// Return either the register or invalid value, because we have no context for213// a good diagnostic message in case of unexpectedly missing references.214const MachineOperand *getFunctionDefinitionByUse(const MachineOperand *Use) {215auto ResF = InstrToFunction.find(Use);216if (ResF == InstrToFunction.end())217return nullptr;218auto ResReg = FunctionToInstr.find(ResF->second);219return ResReg == FunctionToInstr.end() ? nullptr : ResReg->second;220}221222// Map a Function to a machine instruction that represents the function223// definition.224const MachineInstr *getFunctionDefinition(const Function *F) {225if (!F)226return nullptr;227auto MOIt = FunctionToInstr.find(F);228return MOIt == FunctionToInstr.end() ? nullptr : MOIt->second->getParent();229}230231// Map a Function to a machine instruction that represents the function232// definition.233const Function *getFunctionByDefinition(const MachineInstr *MI) {234if (!MI)235return nullptr;236auto FIt = FunctionToInstrRev.find(MI);237return FIt == FunctionToInstrRev.end() ? nullptr : FIt->second;238}239240// map function pointer (as a machine instruction operand) to the used241// Function242void recordFunctionPointer(const MachineOperand *MO, const Function *F) {243InstrToFunction[MO] = F;244}245246// map a Function to its definition (as a machine instruction)247void recordFunctionDefinition(const Function *F, const MachineOperand *MO) {248FunctionToInstr[F] = MO;249FunctionToInstrRev[MO->getParent()] = F;250}251252// Return true if any OpConstantFunctionPointerINTEL were generated253bool hasConstFunPtr() { return !InstrToFunction.empty(); }254255// Add a record about forward function call.256void addForwardCall(const Function *F, MachineInstr *MI) {257auto It = ForwardCalls.find(F);258if (It == ForwardCalls.end())259ForwardCalls[F] = {MI};260else261It->second.insert(MI);262}263264// Map a Function to the vector of machine instructions that represents265// forward function calls or to nullptr if not found.266SmallPtrSet<MachineInstr *, 8> *getForwardCalls(const Function *F) {267auto It = ForwardCalls.find(F);268return It == ForwardCalls.end() ? nullptr : &It->second;269}270271// Get or create a SPIR-V type corresponding the given LLVM IR type,272// and map it to the given VReg by creating an ASSIGN_TYPE instruction.273SPIRVType *assignTypeToVReg(const Type *Type, Register VReg,274MachineIRBuilder &MIRBuilder,275SPIRV::AccessQualifier::AccessQualifier AQ =276SPIRV::AccessQualifier::ReadWrite,277bool EmitIR = true);278SPIRVType *assignIntTypeToVReg(unsigned BitWidth, Register VReg,279MachineInstr &I, const SPIRVInstrInfo &TII);280SPIRVType *assignFloatTypeToVReg(unsigned BitWidth, Register VReg,281MachineInstr &I, const SPIRVInstrInfo &TII);282SPIRVType *assignVectTypeToVReg(SPIRVType *BaseType, unsigned NumElements,283Register VReg, MachineInstr &I,284const SPIRVInstrInfo &TII);285286// In cases where the SPIR-V type is already known, this function can be287// used to map it to the given VReg via an ASSIGN_TYPE instruction.288void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg,289MachineFunction &MF);290291// Either generate a new OpTypeXXX instruction or return an existing one292// corresponding to the given LLVM IR type.293// EmitIR controls if we emit GMIR or SPV constants (e.g. for array sizes)294// because this method may be called from InstructionSelector and we don't295// want to emit extra IR instructions there.296SPIRVType *getOrCreateSPIRVType(const Type *Type,297MachineIRBuilder &MIRBuilder,298SPIRV::AccessQualifier::AccessQualifier AQ =299SPIRV::AccessQualifier::ReadWrite,300bool EmitIR = true);301302const Type *getTypeForSPIRVType(const SPIRVType *Ty) const {303auto Res = SPIRVToLLVMType.find(Ty);304assert(Res != SPIRVToLLVMType.end());305return Res->second;306}307308// Return a pointee's type, or nullptr otherwise.309SPIRVType *getPointeeType(SPIRVType *PtrType);310// Return a pointee's type op code, or 0 otherwise.311unsigned getPointeeTypeOp(Register PtrReg);312313// Either generate a new OpTypeXXX instruction or return an existing one314// corresponding to the given string containing the name of the builtin type.315// Return nullptr if unable to recognize SPIRV type name from `TypeStr`.316SPIRVType *getOrCreateSPIRVTypeByName(317StringRef TypeStr, MachineIRBuilder &MIRBuilder,318SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::Function,319SPIRV::AccessQualifier::AccessQualifier AQ =320SPIRV::AccessQualifier::ReadWrite);321322// Return the SPIR-V type instruction corresponding to the given VReg, or323// nullptr if no such type instruction exists. The second argument MF324// allows to search for the association in a context of the machine functions325// than the current one, without switching between different "current" machine326// functions.327SPIRVType *getSPIRVTypeForVReg(Register VReg,328const MachineFunction *MF = nullptr) const;329330// Whether the given VReg has a SPIR-V type mapped to it yet.331bool hasSPIRVTypeForVReg(Register VReg) const {332return getSPIRVTypeForVReg(VReg) != nullptr;333}334335// Return the VReg holding the result of the given OpTypeXXX instruction.336Register getSPIRVTypeID(const SPIRVType *SpirvType) const;337338// Return previous value of the current machine function339MachineFunction *setCurrentFunc(MachineFunction &MF) {340MachineFunction *Ret = CurMF;341CurMF = &MF;342return Ret;343}344345// Return true if the type is an aggregate type.346bool isAggregateType(SPIRVType *Type) const {347return Type && (Type->getOpcode() == SPIRV::OpTypeStruct &&348Type->getOpcode() == SPIRV::OpTypeArray);349}350351// Whether the given VReg has an OpTypeXXX instruction mapped to it with the352// given opcode (e.g. OpTypeFloat).353bool isScalarOfType(Register VReg, unsigned TypeOpcode) const;354355// Return true if the given VReg's assigned SPIR-V type is either a scalar356// matching the given opcode, or a vector with an element type matching that357// opcode (e.g. OpTypeBool, or OpTypeVector %x 4, where %x is OpTypeBool).358bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const;359360// Return number of elements in a vector if the argument is associated with361// a vector type. Return 1 for a scalar type, and 0 for a missing type.362unsigned getScalarOrVectorComponentCount(Register VReg) const;363unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const;364365// For vectors or scalars of booleans, integers and floats, return the scalar366// type's bitwidth. Otherwise calls llvm_unreachable().367unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const;368369// For vectors or scalars of integers and floats, return total bitwidth of the370// argument. Otherwise returns 0.371unsigned getNumScalarOrVectorTotalBitWidth(const SPIRVType *Type) const;372373// Returns either pointer to integer type, that may be a type of vector374// elements or an original type, or nullptr if the argument is niether375// an integer scalar, nor an integer vector376const SPIRVType *retrieveScalarOrVectorIntType(const SPIRVType *Type) const;377378// For integer vectors or scalars, return whether the integers are signed.379bool isScalarOrVectorSigned(const SPIRVType *Type) const;380381// Gets the storage class of the pointer type assigned to this vreg.382SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const;383384// Return the number of bits SPIR-V pointers and size_t variables require.385unsigned getPointerSize() const { return PointerSize; }386387// Returns true if two types are defined and are compatible in a sense of388// OpBitcast instruction389bool isBitcastCompatible(const SPIRVType *Type1,390const SPIRVType *Type2) const;391392private:393SPIRVType *getOpTypeBool(MachineIRBuilder &MIRBuilder);394395const Type *adjustIntTypeByWidth(const Type *Ty) const;396unsigned adjustOpTypeIntWidth(unsigned Width) const;397398SPIRVType *getOpTypeInt(unsigned Width, MachineIRBuilder &MIRBuilder,399bool IsSigned = false);400401SPIRVType *getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder);402403SPIRVType *getOpTypeVoid(MachineIRBuilder &MIRBuilder);404405SPIRVType *getOpTypeVector(uint32_t NumElems, SPIRVType *ElemType,406MachineIRBuilder &MIRBuilder);407408SPIRVType *getOpTypeArray(uint32_t NumElems, SPIRVType *ElemType,409MachineIRBuilder &MIRBuilder, bool EmitIR = true);410411SPIRVType *getOpTypeOpaque(const StructType *Ty,412MachineIRBuilder &MIRBuilder);413414SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder,415bool EmitIR = true);416417SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC,418SPIRVType *ElemType, MachineIRBuilder &MIRBuilder,419Register Reg);420421SPIRVType *getOpTypeForwardPointer(SPIRV::StorageClass::StorageClass SC,422MachineIRBuilder &MIRBuilder);423424SPIRVType *getOpTypeFunction(SPIRVType *RetType,425const SmallVectorImpl<SPIRVType *> &ArgTypes,426MachineIRBuilder &MIRBuilder);427428SPIRVType *429getOrCreateSpecialType(const Type *Ty, MachineIRBuilder &MIRBuilder,430SPIRV::AccessQualifier::AccessQualifier AccQual);431432std::tuple<Register, ConstantInt *, bool> getOrCreateConstIntReg(433uint64_t Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,434MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);435std::tuple<Register, ConstantFP *, bool, unsigned> getOrCreateConstFloatReg(436APFloat Val, SPIRVType *SpvType, MachineIRBuilder *MIRBuilder,437MachineInstr *I = nullptr, const SPIRVInstrInfo *TII = nullptr);438SPIRVType *finishCreatingSPIRVType(const Type *LLVMTy, SPIRVType *SpirvType);439Register getOrCreateBaseRegister(Constant *Val, MachineInstr &I,440SPIRVType *SpvType,441const SPIRVInstrInfo &TII,442unsigned BitWidth);443Register getOrCreateCompositeOrNull(Constant *Val, MachineInstr &I,444SPIRVType *SpvType,445const SPIRVInstrInfo &TII, Constant *CA,446unsigned BitWidth, unsigned ElemCnt,447bool ZeroAsNull = true);448449Register getOrCreateIntCompositeOrNull(uint64_t Val,450MachineIRBuilder &MIRBuilder,451SPIRVType *SpvType, bool EmitIR,452Constant *CA, unsigned BitWidth,453unsigned ElemCnt);454455public:456Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder,457SPIRVType *SpvType = nullptr, bool EmitIR = true);458Register getOrCreateConstInt(uint64_t Val, MachineInstr &I,459SPIRVType *SpvType, const SPIRVInstrInfo &TII,460bool ZeroAsNull = true);461Register getOrCreateConstFP(APFloat Val, MachineInstr &I, SPIRVType *SpvType,462const SPIRVInstrInfo &TII,463bool ZeroAsNull = true);464Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder,465SPIRVType *SpvType = nullptr);466467Register getOrCreateConstVector(uint64_t Val, MachineInstr &I,468SPIRVType *SpvType, const SPIRVInstrInfo &TII,469bool ZeroAsNull = true);470Register getOrCreateConstVector(APFloat Val, MachineInstr &I,471SPIRVType *SpvType, const SPIRVInstrInfo &TII,472bool ZeroAsNull = true);473Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I,474SPIRVType *SpvType,475const SPIRVInstrInfo &TII);476Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder,477SPIRVType *SpvType, bool EmitIR = true);478Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder,479SPIRVType *SpvType);480Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param,481unsigned FilerMode,482MachineIRBuilder &MIRBuilder,483SPIRVType *SpvType);484Register getOrCreateUndef(MachineInstr &I, SPIRVType *SpvType,485const SPIRVInstrInfo &TII);486Register buildGlobalVariable(Register Reg, SPIRVType *BaseType,487StringRef Name, const GlobalValue *GV,488SPIRV::StorageClass::StorageClass Storage,489const MachineInstr *Init, bool IsConst,490bool HasLinkageTy,491SPIRV::LinkageType::LinkageType LinkageType,492MachineIRBuilder &MIRBuilder,493bool IsInstSelector);494495// Convenient helpers for getting types with check for duplicates.496SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth,497MachineIRBuilder &MIRBuilder);498SPIRVType *getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineInstr &I,499const SPIRVInstrInfo &TII);500SPIRVType *getOrCreateSPIRVType(unsigned BitWidth, MachineInstr &I,501const SPIRVInstrInfo &TII,502unsigned SPIRVOPcode, Type *LLVMTy);503SPIRVType *getOrCreateSPIRVFloatType(unsigned BitWidth, MachineInstr &I,504const SPIRVInstrInfo &TII);505SPIRVType *getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder);506SPIRVType *getOrCreateSPIRVBoolType(MachineInstr &I,507const SPIRVInstrInfo &TII);508SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType,509unsigned NumElements,510MachineIRBuilder &MIRBuilder);511SPIRVType *getOrCreateSPIRVVectorType(SPIRVType *BaseType,512unsigned NumElements, MachineInstr &I,513const SPIRVInstrInfo &TII);514SPIRVType *getOrCreateSPIRVArrayType(SPIRVType *BaseType,515unsigned NumElements, MachineInstr &I,516const SPIRVInstrInfo &TII);517518SPIRVType *getOrCreateSPIRVPointerType(519SPIRVType *BaseType, MachineIRBuilder &MIRBuilder,520SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);521SPIRVType *getOrCreateSPIRVPointerType(522SPIRVType *BaseType, MachineInstr &I, const SPIRVInstrInfo &TII,523SPIRV::StorageClass::StorageClass SClass = SPIRV::StorageClass::Function);524525SPIRVType *526getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType,527SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed,528uint32_t Multisampled, uint32_t Sampled,529SPIRV::ImageFormat::ImageFormat ImageFormat,530SPIRV::AccessQualifier::AccessQualifier AccQual);531532SPIRVType *getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder);533534SPIRVType *getOrCreateOpTypeSampledImage(SPIRVType *ImageType,535MachineIRBuilder &MIRBuilder);536SPIRVType *getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder,537const TargetExtType *ExtensionType,538const SPIRVType *ElemType,539uint32_t Scope, uint32_t Rows,540uint32_t Columns, uint32_t Use);541SPIRVType *542getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder,543SPIRV::AccessQualifier::AccessQualifier AccQual);544SPIRVType *getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder);545SPIRVType *getOrCreateOpTypeFunctionWithArgs(546const Type *Ty, SPIRVType *RetType,547const SmallVectorImpl<SPIRVType *> &ArgTypes,548MachineIRBuilder &MIRBuilder);549SPIRVType *getOrCreateOpTypeByOpcode(const Type *Ty,550MachineIRBuilder &MIRBuilder,551unsigned Opcode);552};553} // end namespace llvm554#endif // LLLVM_LIB_TARGET_SPIRV_SPIRVTYPEMANAGER_H555556557