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 assert(
Use.getOpcode() == TargetOpcode::G_BUILD_VECTOR &&
71 "Expected use of G_UNMERGE_VALUES to be a G_BUILD_VECTOR");
84 for (
unsigned i = 0; i <
I->getNumDefs(); ++i) {
85 Register DefReg =
I->getOperand(i).getReg();
89 LLT DefLLT =
MRI.getType(DefReg);
108 Register ResVReg =
I->getOperand(0).getReg();
122 unsigned StartOp,
unsigned EndOp) {
124 for (
unsigned i = StartOp; i < EndOp; ++i) {
126#ifdef EXPENSIVE_CHECKS
127 assert(!ResType ||
Type == ResType &&
"Conflicting type from operands.");
163 switch (
Use.getOpcode()) {
164 case TargetOpcode::G_BUILD_VECTOR:
165 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
166 case TargetOpcode::G_UNMERGE_VALUES:
180 Register ResVReg =
I->getOperand(0).getReg();
181 switch (
I->getOpcode()) {
182 case TargetOpcode::G_CONSTANT:
183 case TargetOpcode::G_ANYEXT:
185 case TargetOpcode::G_BUILD_VECTOR:
187 case TargetOpcode::G_SHUFFLE_VECTOR:
190 if (
I->getNumDefs() == 1 &&
I->getNumOperands() > 1 &&
191 I->getOperand(1).isReg())
202 Register ResVReg =
I->getOperand(0).getReg();
207 if (
I->getOpcode() == TargetOpcode::G_UNMERGE_VALUES)
223 if (!
MRI.getRegClassOrNull(ResVReg)) {
232 LLVM_DEBUG(
dbgs() <<
"Checking if instruction requires a SPIR-V type: "
234 if (
I.getNumDefs() == 0) {
235 LLVM_DEBUG(
dbgs() <<
"Instruction does not have a definition.\n");
239 if (!
I.isPreISelOpcode()) {
240 LLVM_DEBUG(
dbgs() <<
"Instruction is not a generic instruction.\n");
244 Register ResultRegister =
I.defs().begin()->getReg();
247 if (!
MRI.getRegClassOrNull(ResultRegister)) {
270 if (Worklist.
empty()) {
276 for (
auto *
I : Worklist) {
I->dump(); });
291 Worklist = std::move(NextWorklist);
292 LLVM_DEBUG(
dbgs() <<
"Worklist size: " << Worklist.size() <<
"\n");
295 if (Worklist.
empty())
298 for (
auto *
I : Worklist) {
300 Register ResVReg =
I->getOperand(0).getReg();
301 const LLT &ResLLT =
MRI.getType(ResVReg);
312 <<
", defaulting to " << *ResType <<
"\n");
319 LLVM_DEBUG(
dbgs() <<
"Entering ensureAssignTypeForTypeFolding for function "
326 if (
MI.getNumOperands() == 1 || !
MI.getOperand(1).isReg())
332 bool HasAssignType =
false;
333 Register ResultRegister =
MI.defs().begin()->getReg();
336 MRI.use_nodbg_instructions(ResultRegister)) {
337 if (UseInstr.getOpcode() == SPIRV::ASSIGN_TYPE) {
338 HasAssignType =
true;
339 LLVM_DEBUG(
dbgs() <<
" Instruction already has an ASSIGN_TYPE use: "
345 if (!HasAssignType) {
346 Register ResultRegister =
MI.defs().begin()->getReg();
349 dbgs() <<
" Adding ASSIGN_TYPE for ResultRegister: "
350 <<
printReg(ResultRegister,
MRI.getTargetRegisterInfo())
351 <<
" with type: " << *ResultType);
363 std::stack<MachineBasicBlock *> ToVisit;
366 ToVisit.push(&Start);
367 Seen.
insert(ToVisit.top());
368 while (ToVisit.size() != 0) {
374 for (
auto Succ :
MBB->successors()) {
392 SPIRVGlobalRegistry *GR =
ST.getSPIRVGlobalRegistry();
393 GR->setCurrentFunc(MF);
402char SPIRVPostLegalizer::
ID = 0;
405 return new SPIRVPostLegalizer();
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 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 * deduceTypeForResultRegister(MachineInstr *Use, Register UseRegister, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB)
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.
MachineRegisterInfo * getMRI()
Getter for MRI.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
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)
SPIRVType * getScalarOrVectorComponentType(Register VReg) 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.
void insertAssignInstr(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)
Helper external function for inserting ASSIGN_TYPE instuction between Reg and its definition,...
bool isTypeFoldingSupported(unsigned Opcode)
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
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.