20#include "llvm/IR/IntrinsicsSPIRV.h"
24#define DEBUG_TYPE "spirv-postlegalizer"
57 Register SrcReg =
I->getOperand(
I->getNumOperands() - 1).getReg();
60 assert(DefType->getOpcode() == SPIRV::OpTypeVector);
67 for (
unsigned i = 0; i <
I->getNumDefs() && !ScalarType; ++i) {
68 for (
const auto &
Use :
69 MRI.use_nodbg_instructions(
I->getOperand(i).getReg())) {
70 if (
Use.getOpcode() != TargetOpcode::G_BUILD_VECTOR)
85 for (
unsigned i = 0; i <
I->getNumDefs(); ++i) {
86 Register DefReg =
I->getOperand(i).getReg();
90 LLT DefLLT =
MRI.getType(DefReg);
109 Register ResVReg =
I->getOperand(0).getReg();
123 unsigned StartOp,
unsigned EndOp) {
125 for (
unsigned i = StartOp; i < EndOp; ++i) {
127#ifdef EXPENSIVE_CHECKS
128 assert(!ResType ||
Type == ResType &&
"Conflicting type from operands.");
165 switch (
Use.getOpcode()) {
166 case TargetOpcode::G_BUILD_VECTOR:
167 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
168 case TargetOpcode::G_UNMERGE_VALUES:
169 case TargetOpcode::G_ADD:
170 case TargetOpcode::G_SUB:
171 case TargetOpcode::G_MUL:
172 case TargetOpcode::G_SDIV:
173 case TargetOpcode::G_UDIV:
174 case TargetOpcode::G_SREM:
175 case TargetOpcode::G_UREM:
176 case TargetOpcode::G_FADD:
177 case TargetOpcode::G_FSUB:
178 case TargetOpcode::G_FMUL:
179 case TargetOpcode::G_FDIV:
180 case TargetOpcode::G_FREM:
181 case TargetOpcode::G_FMA:
182 case TargetOpcode::G_STRICT_FMA:
185 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
186 case TargetOpcode::G_INTRINSIC: {
188 if (IntrinsicID == Intrinsic::spv_insertelt) {
189 if (
Reg ==
Use.getOperand(2).getReg())
191 }
else if (IntrinsicID == Intrinsic::spv_extractelt) {
192 if (
Reg ==
Use.getOperand(2).getReg())
209 Register ResVReg =
I->getOperand(0).getReg();
210 switch (
I->getOpcode()) {
211 case TargetOpcode::G_CONSTANT:
212 case TargetOpcode::G_ANYEXT:
214 case TargetOpcode::G_BUILD_VECTOR:
216 case TargetOpcode::G_SHUFFLE_VECTOR:
219 if (
I->getNumDefs() == 1 &&
I->getNumOperands() > 1 &&
220 I->getOperand(1).isReg())
231 Register ResVReg =
I->getOperand(0).getReg();
236 if (
I->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
252 if (!
MRI.getRegClassOrNull(ResVReg)) {
261 LLVM_DEBUG(
dbgs() <<
"Checking if instruction requires a SPIR-V type: "
263 if (
I.getNumDefs() == 0) {
264 LLVM_DEBUG(
dbgs() <<
"Instruction does not have a definition.\n");
268 if (!
I.isPreISelOpcode()) {
269 LLVM_DEBUG(
dbgs() <<
"Instruction is not a generic instruction.\n");
273 Register ResultRegister =
I.defs().begin()->getReg();
276 if (!
MRI.getRegClassOrNull(ResultRegister)) {
299 if (Worklist.
empty()) {
305 for (
auto *
I : Worklist) {
I->dump(); });
320 Worklist = std::move(NextWorklist);
321 LLVM_DEBUG(
dbgs() <<
"Worklist size: " << Worklist.size() <<
"\n");
324 if (Worklist.
empty())
327 for (
auto *
I : Worklist) {
329 for (
unsigned Idx = 0; Idx <
I->getNumDefs(); ++Idx) {
330 Register ResVReg =
I->getOperand(Idx).getReg();
333 const LLT &ResLLT =
MRI.getType(ResVReg);
344 <<
", defaulting to " << *ResType <<
"\n");
353 if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
364 <<
printReg(ResultRegister,
MRI.getTargetRegisterInfo())
365 <<
" with type: " << *ResultType);
373 MRI.createGenericVirtualRegister(
MRI.getType(ResultRegister));
374 const auto *RegClass = GR->
getRegClass(ResultType);
375 MRI.setRegClass(NewReg, RegClass);
376 MRI.setRegClass(ResultRegister, RegClass);
390 for (
unsigned I = 0,
E =
MI.getNumDefs();
I !=
E; ++
I) {
392 if (MO.
getReg() == ResultRegister) {
401 LLVM_DEBUG(
dbgs() <<
"Entering ensureAssignTypeForTypeFolding for function "
411 Register ResultRegister =
MI.defs().begin()->getReg();
428 std::stack<MachineBasicBlock *> ToVisit;
431 ToVisit.push(&Start);
432 Seen.
insert(ToVisit.top());
433 while (ToVisit.size() != 0) {
439 for (
auto Succ :
MBB->successors()) {
457 SPIRVGlobalRegistry *GR =
ST.getSPIRVGlobalRegistry();
458 GR->setCurrentFunc(MF);
467char SPIRVPostLegalizer::
ID = 0;
470 return new SPIRVPostLegalizer();
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool deduceAndAssignSpirvType(MachineInstr *I, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVType * deduceIntTypeFromResult(Register ResVReg, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR)
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
static void registerSpirvTypeForNewInstructions(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static bool hasAssignType(Register Reg, MachineRegisterInfo &MRI)
static SPIRVType * deduceResultTypeFromOperands(MachineInstr *I, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVType * deduceTypeFromOperandRange(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned StartOp, unsigned EndOp)
static SPIRVType * deduceTypeFromUses(Register Reg, MachineFunction &MF, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static SPIRVType * deduceTypeFromResultRegister(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
static void generateAssignType(MachineInstr &MI, Register ResultRegister, SPIRVType *ResultType, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)
static bool deduceAndAssignTypeForGUnmerge(MachineInstr *I, MachineFunction &MF, SPIRVGlobalRegistry *GR)
static void ensureAssignTypeForTypeFolding(MachineFunction &MF, SPIRVGlobalRegistry *GR)
static bool requiresSpirvType(MachineInstr &I, SPIRVGlobalRegistry *GR, MachineRegisterInfo &MRI)
static SPIRVType * deduceTypeFromSingleOperand(MachineInstr *I, MachineIRBuilder &MIB, SPIRVGlobalRegistry *GR, unsigned OpIdx)
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
MachineRegisterInfo * getMRI()
Getter for MRI.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
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,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
Wrapper class representing virtual and physical registers.
SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
Register getSPIRVTypeID(const SPIRVType *SpirvType) const
SPIRVType * getScalarOrVectorComponentType(Register VReg) const
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)
SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)
const SPIRVInstrInfo * getInstrInfo() const override
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
A Use represents the edge between a Value definition and its users.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
bool isTypeFoldingSupported(unsigned Opcode)
void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for assigning SPIRVType to a register, ensuring the register class and type ...
void processInstr(MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR, SPIRVType *KnownResType)
FunctionPass * createSPIRVPostLegalizerPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void setRegClassType(Register Reg, SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF, bool Force)
const MachineInstr SPIRVType
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.