23#include "llvm/IR/IntrinsicsSPIRV.h"
25#define DEBUG_TYPE "spirv-lower"
51 if (Ty1->
getOpcode() == SPIRV::OpTypeArray) {
60 return ElemType1 == ElemType2 ||
64 if (Ty1->
getOpcode() == SPIRV::OpTypeStruct) {
70 if (ElemType1 != ElemType2 &&
112 unsigned AlignIdx = 3;
114 case Intrinsic::spv_load:
117 case Intrinsic::spv_store: {
118 if (
I.getNumOperands() >= AlignIdx + 1) {
120 Info.align =
Align(AlignOp->getZExtValue());
124 Info.memVT = MVT::i64;
144std::pair<unsigned, const TargetRegisterClass *>
150 return std::make_pair(0u, RC);
153 RC = VT.
isVector() ? &SPIRV::vfIDRegClass : &SPIRV::fIDRegClass;
155 RC = VT.
isVector() ? &SPIRV::vIDRegClass : &SPIRV::iIDRegClass;
157 RC = &SPIRV::iIDRegClass;
159 return std::make_pair(0u, RC);
164 return Inst && Inst->
getOpcode() == SPIRV::OpFunctionParameter
181 I.getOperand(
OpIdx).setReg(NewReg);
188 SPIRV::StorageClass::StorageClass SC =
189 static_cast<SPIRV::StorageClass::StorageClass
>(
190 OpType->getOperand(1).
getImm());
195 ResTy, MIB, SPIRV::AccessQualifier::ReadWrite,
false);
205 const Type *ResTy =
nullptr) {
211 if (!ResType || !OpType || OpType->
getOpcode() != SPIRV::OpTypePointer)
214 Register ElemTypeReg = OpType->getOperand(2).getReg();
220 bool IsEqualTypes = IsSameMF ? ElemType == ResType
230 "insert validation bitcast: incompatible result and operand types");
240 constexpr unsigned OpIdx = 2;
245 if (!OpType || OpType->getOpcode() != SPIRV::OpTypePointer)
249 if (!ElemType || ElemType->
getOpcode() == SPIRV::OpTypeEvent)
262 Register PtrReg =
I.getOperand(0).getReg();
267 if (!PonteeElemType || PonteeElemType->
getOpcode() == SPIRV::OpTypeVoid ||
268 (PonteeElemType->
getOpcode() == SPIRV::OpTypeInt &&
272 SPIRV::StorageClass::StorageClass SC =
273 static_cast<SPIRV::StorageClass::StorageClass
>(
290 if (!OpType || OpType->getOpcode() != SPIRV::OpTypePointer)
294 if (!ElemType || ElemType->
getOpcode() != SPIRV::OpTypeStruct ||
302 unsigned MemberTypeOp = MemberType->
getOpcode();
303 if (MemberTypeOp != SPIRV::OpTypeVector && MemberTypeOp != SPIRV::OpTypeInt &&
304 MemberTypeOp != SPIRV::OpTypeFloat && MemberTypeOp != SPIRV::OpTypeBool)
308 SPIRV::StorageClass::StorageClass SC =
309 static_cast<SPIRV::StorageClass::StorageClass
>(
310 OpType->getOperand(1).
getImm());
330 if (FunDef->
getOpcode() != SPIRV::OpFunction)
334 FunDef && FunDef->
getOpcode() == SPIRV::OpFunctionParameter &&
340 DefPtrType && DefPtrType->
getOpcode() == SPIRV::OpTypePointer
386 &FunCall->getParent()->getParent()->getRegInfo();
395 if (BaseTypeInst && BaseTypeInst->
getOpcode() == SPIRV::OpTypePointer) {
407 if (ProcessedMF.find(&MF) != ProcessedMF.end())
418 switch (
MI.getOpcode()) {
419 case SPIRV::OpAtomicLoad:
420 case SPIRV::OpAtomicExchange:
421 case SPIRV::OpAtomicCompareExchange:
422 case SPIRV::OpAtomicCompareExchangeWeak:
423 case SPIRV::OpAtomicIIncrement:
424 case SPIRV::OpAtomicIDecrement:
425 case SPIRV::OpAtomicIAdd:
426 case SPIRV::OpAtomicISub:
427 case SPIRV::OpAtomicSMin:
428 case SPIRV::OpAtomicUMin:
429 case SPIRV::OpAtomicSMax:
430 case SPIRV::OpAtomicUMax:
431 case SPIRV::OpAtomicAnd:
432 case SPIRV::OpAtomicOr:
433 case SPIRV::OpAtomicXor:
445 case SPIRV::OpAtomicStore:
456 case SPIRV::OpPtrCastToGeneric:
457 case SPIRV::OpGenericCastToPtr:
458 case SPIRV::OpGenericCastToPtrExplicit:
461 case SPIRV::OpPtrAccessChain:
462 case SPIRV::OpInBoundsPtrAccessChain:
463 if (
MI.getNumOperands() == 4)
467 case SPIRV::OpFunctionCall:
470 if (
MI.getNumOperands() > 3)
474 case SPIRV::OpFunction:
488 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual));
493 case SPIRV::OpBitwiseOrS:
494 case SPIRV::OpBitwiseOrV:
497 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalOr));
499 case SPIRV::OpBitwiseAndS:
500 case SPIRV::OpBitwiseAndV:
503 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalAnd));
505 case SPIRV::OpBitwiseXorS:
506 case SPIRV::OpBitwiseXorV:
509 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpLogicalNotEqual));
511 case SPIRV::OpLifetimeStart:
512 case SPIRV::OpLifetimeStop:
513 if (
MI.getOperand(1).getImm() > 0)
516 case SPIRV::OpGroupAsyncCopy:
520 case SPIRV::OpGroupWaitEvents:
524 case SPIRV::OpConstantI: {
526 if (
Type->getOpcode() != SPIRV::OpTypeInt &&
MI.getOperand(2).isImm() &&
527 MI.getOperand(2).getImm() == 0) {
529 MI.setDesc(STI.getInstrInfo()->get(SPIRV::OpConstantNull));
530 for (
unsigned i =
MI.getNumOperands() - 1; i > 1; --i)
534 case SPIRV::OpExtInst: {
536 if (!
MI.getOperand(2).isImm() || !
MI.getOperand(3).isImm() ||
537 MI.getOperand(2).getImm() != SPIRV::InstructionSet::OpenCL_std)
539 switch (
MI.getOperand(3).getImm()) {
540 case SPIRV::OpenCLExtInst::frexp:
541 case SPIRV::OpenCLExtInst::lgamma_r:
542 case SPIRV::OpenCLExtInst::remquo: {
548 assert(RetType &&
"Expected return type");
550 RetType->
getOpcode() != SPIRV::OpTypeVector
556 case SPIRV::OpenCLExtInst::fract:
557 case SPIRV::OpenCLExtInst::modf:
558 case SPIRV::OpenCLExtInst::sincos:
561 assert(
MI.getOperand(
MI.getNumOperands() - 2).isReg() &&
564 STI, MRI, GR,
MI,
MI.getNumOperands() - 1,
566 MI.getOperand(
MI.getNumOperands() - 2).getReg()));
568 case SPIRV::OpenCLExtInst::prefetch:
571 assert(
MI.getOperand(
MI.getNumOperands() - 2).isReg() &&
574 MI.getNumOperands() - 2);
595 if (PointeeType == OpType)
600 if (
I.getOperand(
OpIdx).isDef() &&
627 OldResult.
setReg(NewResultReg);
628 OldType.
setReg(NewTypeReg);
636 *STI.getRegBankInfo());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator MBBI
Register const TargetRegisterInfo * TRI
MachineInstr unsigned OpIdx
static bool typesLogicallyMatch(const SPIRVTypeInst Ty1, const SPIRVTypeInst Ty2, SPIRVGlobalRegistry &GR)
static void validateLifetimeStart(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I)
static void validatePtrTypes(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I, unsigned OpIdx, SPIRVTypeInst ResType, const Type *ResTy=nullptr)
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 void doInsertBitcast(const SPIRVSubtarget &STI, MachineRegisterInfo *MRI, SPIRVGlobalRegistry &GR, MachineInstr &I, Register OpReg, unsigned OpIdx, SPIRVTypeInst NewPtrType)
static SPIRVTypeInst createNewPtrType(SPIRVGlobalRegistry &GR, MachineInstr &I, SPIRVTypeInst OpType, bool ReuseType, SPIRVTypeInst ResType, const Type *ResTy)
This file describes how to lower LLVM code to machine code.
an instruction that atomically reads a memory location, combines it with another value,...
@ UIncWrap
Increment one up to a maximum value.
@ FMin
*p = minnum(old, v) minnum matches the behavior of llvm.minnum.
@ FMax
*p = maxnum(old, v) maxnum matches the behavior of llvm.maxnum.
@ UDecWrap
Decrement one until a minimum value or zero.
BinOp getOperation() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
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.
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.
void constrainAllUses(const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, 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.
void addForwardCall(const Function *F, MachineInstr *MI)
SPIRVTypeInst getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
SPIRVTypeInst getOrCreateSPIRVVectorType(SPIRVTypeInst BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVTypeInst getResultType(Register VReg, MachineFunction *MF=nullptr)
const Type * getTypeForSPIRVType(SPIRVTypeInst Ty) const
bool isBitcastCompatible(SPIRVTypeInst Type1, SPIRVTypeInst Type2) const
const MachineInstr * getFunctionDefinition(const Function *F)
SPIRVTypeInst getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)
Register getSPIRVTypeID(SPIRVTypeInst SpirvType) const
SPIRVTypeInst getPointeeType(SPIRVTypeInst PtrType)
SmallPtrSet< MachineInstr *, 8 > * getForwardCalls(const Function *F)
SPIRVTypeInst getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const
MachineFunction * setCurrentFunc(MachineFunction &MF)
SPIRVTypeInst getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
const Function * getFunctionByDefinition(const MachineInstr *MI)
const SPIRVInstrInfo * getInstrInfo() const override
const SPIRVRegisterInfo * getRegisterInfo() const override
const RegisterBankInfo * getRegBankInfo() const override
AtomicExpansionKind shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const override
Returns how the given atomic atomicrmw should be cast by the IR-level AtomicExpand pass.
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...
AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const override
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
void finalizeLowering(MachineFunction &MF) const override
Execute target specific actions to finalize target lowering.
void getTgtMemIntrinsic(SmallVectorImpl< IntrinsicInfo > &Infos, const CallBase &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...
bool insertLogicalCopyOnResult(MachineInstr &I, SPIRVTypeInst 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.
ConstraintType getConstraintType(StringRef Constraint) const override
Given a constraint, return the type of constraint it is for this target.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
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.
virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(const AtomicRMWInst *RMW) const
Returns how the IR-level AtomicExpand pass should expand the given AtomicRMW, if at all.
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
void setMinCmpXchgSizeInBits(unsigned SizeInBits)
Sets the minimum cmpxchg or ll/sc size supported by the backend.
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
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(SPIRVTypeInst 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)
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.