21#include "llvm/IR/IntrinsicsSPIRV.h"
23#define DEBUG_TYPE "spirv-lower"
41 if (Ty1->
getOpcode() == SPIRV::OpTypeArray) {
48 return ElemType1 == ElemType2 ||
52 if (Ty1->
getOpcode() == SPIRV::OpTypeStruct) {
58 if (ElemType1 != ElemType2 &&
100 unsigned AlignIdx = 3;
102 case Intrinsic::spv_load:
105 case Intrinsic::spv_store: {
106 if (
I.getNumOperands() >= AlignIdx + 1) {
108 Info.align =
Align(AlignOp->getZExtValue());
112 Info.memVT = MVT::i64;
124std::pair<unsigned, const TargetRegisterClass *>
130 return std::make_pair(0u, RC);
133 RC = VT.
isVector() ? &SPIRV::vfIDRegClass : &SPIRV::fIDRegClass;
135 RC = VT.
isVector() ? &SPIRV::vIDRegClass : &SPIRV::iIDRegClass;
137 RC = &SPIRV::iIDRegClass;
139 return std::make_pair(0u, RC);
144 return TypeInst && TypeInst->
getOpcode() == SPIRV::OpFunctionParameter
163 I.getOperand(
OpIdx).setReg(NewReg);
169 SPIRV::StorageClass::StorageClass SC =
170 static_cast<SPIRV::StorageClass::StorageClass
>(
171 OpType->getOperand(1).
getImm());
176 ResTy, MIB, SPIRV::AccessQualifier::ReadWrite,
false);
191 if (!ResType || !OpType || OpType->
getOpcode() != SPIRV::OpTypePointer)
194 Register ElemTypeReg = OpType->getOperand(2).getReg();
200 bool IsEqualTypes = IsSameMF ? ElemType == ResType
210 "insert validation bitcast: incompatible result and operand types");
220 constexpr unsigned OpIdx = 2;
225 if (!OpType || OpType->getOpcode() != SPIRV::OpTypePointer)
228 if (!ElemType || ElemType->
getOpcode() == SPIRV::OpTypeEvent)
241 Register PtrReg =
I.getOperand(0).getReg();
246 if (!PonteeElemType || PonteeElemType->
getOpcode() == SPIRV::OpTypeVoid ||
247 (PonteeElemType->
getOpcode() == SPIRV::OpTypeInt &&
251 SPIRV::StorageClass::StorageClass SC =
252 static_cast<SPIRV::StorageClass::StorageClass
>(
269 if (!OpType || OpType->getOpcode() != SPIRV::OpTypePointer)
272 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeStruct ||
280 unsigned MemberTypeOp = MemberType->
getOpcode();
281 if (MemberTypeOp != SPIRV::OpTypeVector && MemberTypeOp != SPIRV::OpTypeInt &&
282 MemberTypeOp != SPIRV::OpTypeFloat && MemberTypeOp != SPIRV::OpTypeBool)
286 SPIRV::StorageClass::StorageClass SC =
287 static_cast<SPIRV::StorageClass::StorageClass
>(
288 OpType->getOperand(1).
getImm());
307 if (FunDef->
getOpcode() != SPIRV::OpFunction)
311 FunDef && FunDef->
getOpcode() == SPIRV::OpFunctionParameter &&
316 DefPtrType && DefPtrType->
getOpcode() == SPIRV::OpTypePointer
362 &FunCall->getParent()->getParent()->getRegInfo();
371 if (BaseTypeInst && BaseTypeInst->
getOpcode() == SPIRV::OpTypePointer) {
383 if (ProcessedMF.find(&MF) != ProcessedMF.end())
395 switch (
MI.getOpcode()) {
396 case SPIRV::OpAtomicLoad:
397 case SPIRV::OpAtomicExchange:
398 case SPIRV::OpAtomicCompareExchange:
399 case SPIRV::OpAtomicCompareExchangeWeak:
400 case SPIRV::OpAtomicIIncrement:
401 case SPIRV::OpAtomicIDecrement:
402 case SPIRV::OpAtomicIAdd:
403 case SPIRV::OpAtomicISub:
404 case SPIRV::OpAtomicSMin:
405 case SPIRV::OpAtomicUMin:
406 case SPIRV::OpAtomicSMax:
407 case SPIRV::OpAtomicUMax:
408 case SPIRV::OpAtomicAnd:
409 case SPIRV::OpAtomicOr:
410 case SPIRV::OpAtomicXor:
422 case SPIRV::OpAtomicStore:
433 case SPIRV::OpPtrCastToGeneric:
434 case SPIRV::OpGenericCastToPtr:
435 case SPIRV::OpGenericCastToPtrExplicit:
438 case SPIRV::OpPtrAccessChain:
439 case SPIRV::OpInBoundsPtrAccessChain:
440 if (
MI.getNumOperands() == 4)
444 case SPIRV::OpFunctionCall:
447 if (
MI.getNumOperands() > 3)
451 case SPIRV::OpFunction:
465 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual));
470 case SPIRV::OpBitwiseOrS:
471 case SPIRV::OpBitwiseOrV:
474 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalOr));
476 case SPIRV::OpBitwiseAndS:
477 case SPIRV::OpBitwiseAndV:
480 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalAnd));
482 case SPIRV::OpBitwiseXorS:
483 case SPIRV::OpBitwiseXorV:
486 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual));
488 case SPIRV::OpLifetimeStart:
489 case SPIRV::OpLifetimeStop:
490 if (
MI.getOperand(1).getImm() > 0)
493 case SPIRV::OpGroupAsyncCopy:
497 case SPIRV::OpGroupWaitEvents:
501 case SPIRV::OpConstantI: {
503 if (
Type->getOpcode() != SPIRV::OpTypeInt &&
MI.getOperand(2).isImm() &&
504 MI.getOperand(2).getImm() == 0) {
506 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpConstantNull));
507 for (
unsigned i =
MI.getNumOperands() - 1; i > 1; --i)
521 case SPIRV::OpExtInst: {
523 if (!
MI.getOperand(2).isImm() || !
MI.getOperand(3).isImm() ||
524 MI.getOperand(2).getImm() != SPIRV::InstructionSet::OpenCL_std)
526 switch (
MI.getOperand(3).getImm()) {
527 case SPIRV::OpenCLExtInst::frexp:
528 case SPIRV::OpenCLExtInst::lgamma_r:
529 case SPIRV::OpenCLExtInst::remquo: {
535 assert(RetType &&
"Expected return type");
537 RetType->
getOpcode() != SPIRV::OpTypeVector
543 case SPIRV::OpenCLExtInst::fract:
544 case SPIRV::OpenCLExtInst::modf:
545 case SPIRV::OpenCLExtInst::sincos:
548 assert(
MI.getOperand(
MI.getNumOperands() - 2).isReg() &&
551 STI,
MRI, GR,
MI,
MI.getNumOperands() - 1,
553 MI.getOperand(
MI.getNumOperands() - 2).getReg()));
555 case SPIRV::OpenCLExtInst::prefetch:
558 assert(
MI.getOperand(
MI.getNumOperands() - 2).isReg() &&
561 MI.getNumOperands() - 2);
587 if (PointeeType == OpType)
592 if (
I.getOperand(
OpIdx).isDef() &&
619 OldResult.
setReg(NewResultReg);
620 OldType.
setReg(NewTypeReg);
628 *STI.getRegBankInfo());
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator MBBI
Register const TargetRegisterInfo * TRI
MachineInstr unsigned OpIdx
static void doInsertBitcast(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I, Register OpReg, unsigned OpIdx, SPIRVType *NewPtrType)
static SPIRVType * createNewPtrType(SPIRVGlobalRegistry &GR, MachineInstr &I, SPIRVType *OpType, bool ReuseType, SPIRVType *ResType, const Type *ResTy)
static void validateLifetimeStart(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I)
static void validateGroupWaitEventsPtr(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I)
static void validatePtrUnwrapStructField(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I, unsigned OpIdx)
Register getTypeReg(MachineRegisterInfo *MRI, Register OpReg)
void validateAccessChain(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I)
void validateFunCallMachineDef(const SPIRVSubtarget &STI, MachineRegisterInfo *DefMRI, MachineRegisterInfo *CallMRI, SPIRVGlobalRegistry &GR, MachineInstr &FunCall, MachineInstr *FunDef)
void validateForwardCalls(const SPIRVSubtarget &STI, MachineRegisterInfo *DefMRI, SPIRVGlobalRegistry &GR, MachineInstr &FunDef)
const Function * validateFunCall(const SPIRVSubtarget &STI, MachineRegisterInfo *CallMRI, SPIRVGlobalRegistry &GR, MachineInstr &FunCall)
static bool typesLogicallyMatch(const SPIRVType *Ty1, const SPIRVType *Ty2, SPIRVGlobalRegistry &GR)
static void validatePtrTypes(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I, unsigned OpIdx, SPIRVType *ResType, const Type *ResTy=nullptr)
This class represents a function call, abstracting a target machine's calling convention.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
This is an important class for using LLVM in a threaded context.
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
LLVM_ABI MachineInstr * remove_instr(MachineInstr *I)
Remove the possibly bundled instruction from the instruction list without deleting it.
pred_iterator pred_begin()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
void insert(iterator MBBI, MachineBasicBlock *MBB)
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
bool constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineOperand & getOperand(unsigned i) const
Flags
Flags values. These may be or'd together.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
Wrapper class representing virtual and physical registers.
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void addForwardCall(const Function *F, MachineInstr *MI)
SPIRVType * getResultType(Register VReg, MachineFunction *MF=nullptr)
const Type * getTypeForSPIRVType(const SPIRVType *Ty) const
bool isBitcastCompatible(const SPIRVType *Type1, const SPIRVType *Type2) const
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
const MachineInstr * getFunctionDefinition(const Function *F)
SPIRVType * getPointeeType(SPIRVType *PtrType)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SmallPtrSet< MachineInstr *, 8 > * getForwardCalls(const Function *F)
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
MachineFunction * setCurrentFunc(MachineFunction &MF)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
const Function * getFunctionByDefinition(const MachineInstr *MI)
const SPIRVInstrInfo * getInstrInfo() const override
const SPIRVRegisterInfo * getRegisterInfo() const override
const RegisterBankInfo * getRegBankInfo() const override
bool enforcePtrTypeCompatibility(MachineInstr &I, unsigned PtrOpIdx, unsigned OpIdx) const
unsigned getNumRegisters(LLVMContext &Context, EVT VT, std::optional< MVT > RegisterVT=std::nullopt) const override
Return the number of registers that this ValueType will eventually require.
unsigned getNumRegistersForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain targets require unusual breakdowns of certain types.
MVT getRegisterTypeForCallingConv(LLVMContext &Context, CallingConv::ID CC, EVT VT) const override
Certain combinations of ABIs, Targets and features require that types are legal for some operations a...
bool getTgtMemIntrinsic(IntrinsicInfo &Info, const CallInst &I, MachineFunction &MF, unsigned Intrinsic) const override
Given an intrinsic, checks if on the target the intrinsic will need to map to a MemIntrinsicNode (tou...
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
bool insertLogicalCopyOnResult(MachineInstr &I, SPIRVType *NewResultType) const
SPIRVTargetLowering(const TargetMachine &TM, const SPIRVSubtarget &ST)
std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override
Given a physical register constraint (e.g.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
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.
virtual void finalizeLowering(MachineFunction &MF) const
Execute target specific actions to finalize target lowering.
MVT getRegisterType(MVT VT) const
Return the type of registers that this ValueType will eventually require.
TargetLowering(const TargetLowering &)=delete
Primary interface to the complete machine description for the target machine.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This namespace contains an enum with a value for every intrinsic/builtin function known by LLVM.
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
const MachineInstr SPIRVType
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
This struct is a compact representation of a valid (non-zero power of two) alignment.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool isInteger() const
Return true if this is an integer or a vector integer type.