35 #define DEBUG_TYPE "amdgpu-isel" 39 #define GET_GLOBALISEL_IMPL 40 #define AMDGPUSubtarget GCNSubtarget 41 #include "AMDGPUGenGlobalISel.inc" 42 #undef GET_GLOBALISEL_IMPL 43 #undef AMDGPUSubtarget 49 TRI(*STI.getRegisterInfo()), RBI(RBI), TM(TM),
53 #include
"AMDGPUGenGlobalISel.inc" 56 #include
"AMDGPUGenGlobalISel.inc" 63 bool AMDGPUInstructionSelector::selectCOPY(
MachineInstr &
I)
const {
67 I.
setDesc(TII.get(TargetOpcode::COPY));
83 unsigned SubIdx)
const {
92 unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.
getSubReg(), SubIdx);
95 .addReg(Reg, 0, ComposedSubIdx);
121 bool AMDGPUInstructionSelector::selectG_ADD(
MachineInstr &I)
const {
137 BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
144 BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
164 bool AMDGPUInstructionSelector::selectG_GEP(
MachineInstr &I)
const {
165 return selectG_ADD(I);
168 bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(
MachineInstr &I)
const {
177 I.
setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
181 bool AMDGPUInstructionSelector::selectG_INTRINSIC(
MachineInstr &I,
185 switch (IntrinsicID) {
191 return selectImpl(I, CoverageInfo);
201 std::tie(InputPtrReg, RC)
218 unsigned Reg0,
unsigned Reg1,
unsigned Reg2,
unsigned Reg3,
219 unsigned VM,
bool Compr,
unsigned Enabled,
bool Done) {
222 unsigned Opcode = Done ? AMDGPU::EXP_DONE :
AMDGPU::EXP;
223 return BuildMI(BB, Insert, DL, TII.
get(Opcode))
234 bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
242 switch (IntrinsicID) {
268 BuildMI(*BB, &I, DL, TII.get(AMDGPU::IMPLICIT_DEF),
Undef);
270 true, Enabled, Done);
279 bool AMDGPUInstructionSelector::selectG_STORE(
MachineInstr &I)
const {
292 Opcode = AMDGPU::FLAT_STORE_DWORD;
295 Opcode = AMDGPU::FLAT_STORE_DWORDX2;
298 Opcode = AMDGPU::FLAT_STORE_DWORDX3;
301 Opcode = AMDGPU::FLAT_STORE_DWORDX4;
321 bool AMDGPUInstructionSelector::selectG_CONSTANT(
MachineInstr &I)
const {
331 }
else if (ImmOp.
isCImm()) {
340 IsSgpr = RB->
getID() == AMDGPU::SGPRRegBankID;
345 Size = TRI.getRegSizeInBits(*RC);
348 if (Size != 32 && Size != 64)
351 unsigned Opcode = IsSgpr ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
360 &AMDGPU::VGPR_32RegClass;
365 BuildMI(*BB, &I, DL, TII.get(Opcode), LoReg)
368 BuildMI(*BB, &I, DL, TII.get(Opcode), HiReg)
372 BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
389 return MI.
getOpcode() == TargetOpcode::G_CONSTANT;
399 if (PtrMI->
getOpcode() != TargetOpcode::G_GEP)
402 GEPInfo GEPInfo(*PtrMI);
404 for (
unsigned i = 1, e = 3; i < e; ++i) {
416 if (OpBank->
getID() == AMDGPU::SGPRRegBankID)
417 GEPInfo.SgprParts.push_back(GEPOp.
getReg());
419 GEPInfo.VgprParts.push_back(GEPOp.
getReg());
423 getAddrModeInfo(*PtrMI, MRI, AddrInfo);
437 if (!Ptr || isa<UndefValue>(Ptr) || isa<Argument>(Ptr) ||
438 isa<Constant>(Ptr) || isa<GlobalValue>(Ptr))
453 switch (BaseOpcode) {
454 case AMDGPU::S_LOAD_DWORD_IMM:
457 return AMDGPU::S_LOAD_DWORDX2_IMM;
459 return AMDGPU::S_LOAD_DWORDX4_IMM;
461 return AMDGPU::S_LOAD_DWORDX8_IMM;
463 return AMDGPU::S_LOAD_DWORDX16_IMM;
466 case AMDGPU::S_LOAD_DWORD_IMM_ci:
469 return AMDGPU::S_LOAD_DWORDX2_IMM_ci;
471 return AMDGPU::S_LOAD_DWORDX4_IMM_ci;
473 return AMDGPU::S_LOAD_DWORDX8_IMM_ci;
475 return AMDGPU::S_LOAD_DWORDX16_IMM_ci;
478 case AMDGPU::S_LOAD_DWORD_SGPR:
481 return AMDGPU::S_LOAD_DWORDX2_SGPR;
483 return AMDGPU::S_LOAD_DWORDX4_SGPR;
485 return AMDGPU::S_LOAD_DWORDX8_SGPR;
487 return AMDGPU::S_LOAD_DWORDX16_SGPR;
495 for (
const GEPInfo &GEPInfo : AddrInfo) {
496 if (!GEPInfo.VgprParts.empty())
502 bool AMDGPUInstructionSelector::selectSMRD(
MachineInstr &I,
515 if (hasVgprParts(AddrInfo))
525 unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
527 if (!AddrInfo.
empty() && AddrInfo[0].SgprParts.
size() == 1) {
529 const GEPInfo &GEPInfo = AddrInfo[0];
531 unsigned PtrReg = GEPInfo.SgprParts[0];
545 Opcode =
getSmrdOpcode(AMDGPU::S_LOAD_DWORD_IMM_ci, LoadSize);
555 unsigned OffsetReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
556 BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), OffsetReg)
557 .addImm(GEPInfo.Imm);
577 bool AMDGPUInstructionSelector::selectG_LOAD(
MachineInstr &I)
const {
584 unsigned LoadSize = RBI.getSizeInBits(DstReg, MRI, TRI);
589 getAddrModeInfo(I, MRI, AddrInfo);
591 if (selectSMRD(I, AddrInfo)) {
600 Opcode = AMDGPU::FLAT_LOAD_DWORD;
603 Opcode = AMDGPU::FLAT_LOAD_DWORDX2;
624 return selectCOPY(I);
630 return selectImpl(I, CoverageInfo);
631 case TargetOpcode::G_ADD:
632 return selectG_ADD(I);
633 case TargetOpcode::G_INTTOPTR:
634 case TargetOpcode::G_BITCAST:
635 return selectCOPY(I);
636 case TargetOpcode::G_CONSTANT:
637 case TargetOpcode::G_FCONSTANT:
638 return selectG_CONSTANT(I);
639 case TargetOpcode::G_GEP:
640 return selectG_GEP(I);
641 case TargetOpcode::G_IMPLICIT_DEF:
642 return selectG_IMPLICIT_DEF(I);
643 case TargetOpcode::G_INTRINSIC:
644 return selectG_INTRINSIC(I, CoverageInfo);
645 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
646 return selectG_INTRINSIC_W_SIDE_EFFECTS(I, CoverageInfo);
647 case TargetOpcode::G_LOAD:
648 return selectG_LOAD(I);
649 case TargetOpcode::G_STORE:
650 return selectG_STORE(I);
656 AMDGPUInstructionSelector::selectVCSRC(
MachineOperand &Root)
const {
667 AMDGPUInstructionSelector::selectVSRC0(
MachineOperand &Root)
const {
674 AMDGPUInstructionSelector::selectVOP3Mods0(
MachineOperand &Root)
const {
683 AMDGPUInstructionSelector::selectVOP3OMods(
MachineOperand &Root)
const {
692 AMDGPUInstructionSelector::selectVOP3Mods(
MachineOperand &Root)
const {
static MachineInstr * buildEXP(const TargetInstrInfo &TII, MachineInstr *Insert, unsigned Tgt, unsigned Reg0, unsigned Reg1, unsigned Reg2, unsigned Reg3, unsigned VM, bool Compr, unsigned Enabled, bool Done)
constexpr bool isUInt< 32 >(uint64_t x)
static bool isConstant(const MachineInstr &MI)
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
uint64_t getZExtValue() const
Get zero extended value.
This file declares the targeting of the RegisterBankInfo class for AMDGPU.
unsigned getAddrSpace() const
AMDGPU specific subclass of TargetSubtarget.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
iterator_range< mop_iterator > explicit_operands()
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
unsigned getReg() const
getReg - Returns the register number.
static bool isInstrUniform(const MachineInstr &MI)
unsigned getSubReg() const
Address space for 32-bit constant memory.
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
const TargetRegisterClass * getConstrainedRegClassForOperand(const MachineOperand &MO, const MachineRegisterInfo &MRI) const override
APInt trunc(unsigned width) const
Truncate to new width.
unsigned const TargetRegisterInfo * TRI
static const char * getName()
iterator_range< mop_iterator > operands()
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isInternalRead() const
static unsigned getSmrdOpcode(unsigned BaseOpcode, unsigned LoadSize)
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static unsigned getAddrSpace(StringRef R)
AMDGPUInstructionSelector(const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI, const AMDGPUTargetMachine &TM)
bool isEarlyClobber() const
bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override
Select the (possibly generic) instruction I to only use target-specific opcodes.
A description of a memory reference used in the backend.
Address space for constant memory (VTX2)
This file declares the targeting of the InstructionSelector class for AMDGPU.
const HexagonInstrInfo * TII
const ConstantFP * getFPImm() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool isSGPRClass(const TargetRegisterClass *RC) const
#define GET_GLOBALISEL_PREDICATES_INIT
static int64_t getConstant(const MachineInstr *MI)
TargetRegisterInfo interface that is implemented by all hw codegen targets.
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
void ChangeToImmediate(int64_t ImmVal)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value...
TargetInstrInfo - Interface to description of machine instruction set.
const Value * getValue() const
Return the base address of the memory access.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
int64_t getSMRDEncodedOffset(const MCSubtargetInfo &ST, int64_t ByteOffset)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
size_t size() const
size - Get the array size.
bool isCImm() const
isCImm - Test if this is a MO_CImmediate operand.
bool hasOneMemOperand() const
Return true if this instruction has exactly one MachineMemOperand.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Generation getGeneration() const
const RegisterBank * getRegBankOrNull(unsigned Reg) const
Return the register bank of Reg, or null if Reg has not been assigned a register bank or has been ass...
The AMDGPU TargetMachine interface definition for hw codgen targets.
bool isLegalSMRDImmOffset(const MCSubtargetInfo &ST, int64_t ByteOffset)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const APFloat & getValueAPF() const
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Intrinsic::ID getIntrinsicID() const
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
This class implements the register bank concept.
MachineInstr * getUniqueVRegDef(unsigned Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
const TargetRegisterClass * getRegClassForReg(const MachineRegisterInfo &MRI, unsigned Reg) const
Class for arbitrary precision integers.
void addImplicitDefUseOperands(MachineFunction &MF)
Add all implicit def and use operands to this instruction.
#define GET_GLOBALISEL_TEMPORARIES_INIT
const MachineBasicBlock * getParent() const
Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
std::pair< const ArgDescriptor *, const TargetRegisterClass * > getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const
Provides the logic to select generic machine instructions.
Provides AMDGPU specific target descriptions.
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
static MachineOperand CreateImm(int64_t Val)
static const TargetRegisterClass * constrainGenericRegister(unsigned Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)
Constrain the (possibly generic) virtual register Reg to RC.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
LLVM Value Representation.
APInt bitcastToAPInt() const
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
unsigned getLiveInVirtReg(unsigned PReg) const
getLiveInVirtReg - If PReg is a live-in physical register, return the corresponding live-in physical ...
const MachineOperand & getOperand(unsigned i) const
const ConstantInt * getCImm() const
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool empty() const
empty - Check if the array is empty.
unsigned getID() const
Get the identifier of this register bank.