41 CurrCycleInstr(nullptr),
44 TII(*
ST.getInstrInfo()),
45 TRI(
TII.getRegisterInfo()),
46 ClauseUses(
TRI.getNumRegUnits()),
47 ClauseDefs(
TRI.getNumRegUnits()) {
60 return Opcode == AMDGPU::V_DIV_FMAS_F32 || Opcode == AMDGPU::V_DIV_FMAS_F64;
64 return Opcode == AMDGPU::S_GETREG_B32;
68 return Opcode == AMDGPU::S_SETREG_B32 || Opcode == AMDGPU::S_SETREG_IMM32_B32;
72 return Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32;
75 static bool isRFE(
unsigned Opcode) {
76 return Opcode == AMDGPU::S_RFE_B64;
81 case AMDGPU::S_MOVRELS_B32:
82 case AMDGPU::S_MOVRELS_B64:
83 case AMDGPU::S_MOVRELD_B32:
84 case AMDGPU::S_MOVRELD_B64:
97 case AMDGPU::S_SENDMSG:
98 case AMDGPU::S_SENDMSGHALT:
99 case AMDGPU::S_TTRACEDATA:
103 case AMDGPU::DS_PERMUTE_B32:
104 case AMDGPU::DS_BPERMUTE_B32:
109 AMDGPU::OpName::gds);
119 AMDGPU::OpName::simm16);
133 && checkVMEMHazards(MI) > 0)
159 checkReadM0Hazards(MI) > 0)
163 checkReadM0Hazards(MI) > 0)
166 if (MI->
isInlineAsm() && checkInlineAsmHazards(MI) > 0)
169 if (checkAnyInstHazards(MI) > 0)
180 int WaitStates =
std::max(0, checkAnyInstHazards(MI));
183 return std::max(WaitStates, checkSMRDHazards(MI));
186 WaitStates =
std::max(WaitStates, checkVALUHazards(MI));
189 WaitStates =
std::max(WaitStates, checkVMEMHazards(MI));
192 WaitStates =
std::max(WaitStates, checkDPPHazards(MI));
195 WaitStates =
std::max(WaitStates, checkDivFMasHazards(MI));
198 WaitStates =
std::max(WaitStates, checkRWLaneHazards(MI));
201 return std::max(WaitStates, checkInlineAsmHazards(MI));
204 return std::max(WaitStates, checkGetRegHazards(MI));
207 return std::max(WaitStates, checkSetRegHazards(MI));
210 return std::max(WaitStates, checkRFEHazards(MI));
214 return std::max(WaitStates, checkReadM0Hazards(MI));
217 return std::max(WaitStates, checkReadM0Hazards(MI));
223 EmittedInstrs.push_front(
nullptr);
235 if (CurrCycleInstr->
getOpcode() == AMDGPU::IMPLICIT_DEF)
243 EmittedInstrs.push_front(CurrCycleInstr);
250 EmittedInstrs.push_front(
nullptr);
258 CurrCycleInstr =
nullptr;
262 llvm_unreachable(
"hazard recognizer does not support bottom-up scheduling.");
269 int GCNHazardRecognizer::getWaitStatesSince(
277 unsigned Opcode =
MI->getOpcode();
286 int GCNHazardRecognizer::getWaitStatesSinceDef(
291 return IsHazardDef(
MI) &&
MI->modifiesRegister(Reg, TRI);
294 return getWaitStatesSince(IsHazardFn);
297 int GCNHazardRecognizer::getWaitStatesSinceSetReg(
303 return getWaitStatesSince(IsHazardFn);
331 int GCNHazardRecognizer::checkSoftClauseHazards(
MachineInstr *MEM) {
337 bool IsSMRD = TII.
isSMRD(*MEM);
363 if (ClauseDefs.
none())
376 return ClauseDefs.
anyCommon(ClauseUses) ? 1 : 0;
381 int WaitStatesNeeded = 0;
383 WaitStatesNeeded = checkSoftClauseHazards(SMRD);
387 return WaitStatesNeeded;
391 int SmrdSgprWaitStates = 4;
400 int WaitStatesNeededForUse =
401 SmrdSgprWaitStates - getWaitStatesSinceDef(
Use.getReg(), IsHazardDefFn);
402 WaitStatesNeeded =
std::max(WaitStatesNeeded, WaitStatesNeededForUse);
412 int WaitStatesNeededForUse =
413 SmrdSgprWaitStates - getWaitStatesSinceDef(
Use.getReg(),
414 IsBufferHazardDefFn);
415 WaitStatesNeeded =
std::max(WaitStatesNeeded, WaitStatesNeededForUse);
419 return WaitStatesNeeded;
422 int GCNHazardRecognizer::checkVMEMHazards(
MachineInstr* VMEM) {
426 int WaitStatesNeeded = checkSoftClauseHazards(VMEM);
430 const int VmemSgprWaitStates = 5;
437 int WaitStatesNeededForUse =
438 VmemSgprWaitStates - getWaitStatesSinceDef(
Use.getReg(), IsHazardDefFn);
439 WaitStatesNeeded =
std::max(WaitStatesNeeded, WaitStatesNeededForUse);
441 return WaitStatesNeeded;
449 int DppVgprWaitStates = 2;
450 int DppExecWaitStates = 5;
451 int WaitStatesNeeded = 0;
457 int WaitStatesNeededForUse =
458 DppVgprWaitStates - getWaitStatesSinceDef(
Use.getReg());
459 WaitStatesNeeded =
std::max(WaitStatesNeeded, WaitStatesNeededForUse);
464 DppExecWaitStates - getWaitStatesSinceDef(AMDGPU::EXEC, IsHazardDefFn));
466 return WaitStatesNeeded;
469 int GCNHazardRecognizer::checkDivFMasHazards(
MachineInstr *DivFMas) {
474 const int DivFMasWaitStates = 4;
476 int WaitStatesNeeded = getWaitStatesSinceDef(AMDGPU::VCC, IsHazardDefFn);
478 return DivFMasWaitStates - WaitStatesNeeded;
481 int GCNHazardRecognizer::checkGetRegHazards(
MachineInstr *GetRegInstr) {
483 unsigned GetRegHWReg =
getHWReg(TII, *GetRegInstr);
485 const int GetRegWaitStates = 2;
487 return GetRegHWReg ==
getHWReg(TII, *MI);
489 int WaitStatesNeeded = getWaitStatesSinceSetReg(IsHazardFn);
491 return GetRegWaitStates - WaitStatesNeeded;
494 int GCNHazardRecognizer::checkSetRegHazards(
MachineInstr *SetRegInstr) {
496 unsigned HWReg =
getHWReg(TII, *SetRegInstr);
498 const int SetRegWaitStates =
503 int WaitStatesNeeded = getWaitStatesSinceSetReg(IsHazardFn);
504 return SetRegWaitStates - WaitStatesNeeded;
507 int GCNHazardRecognizer::createsVALUHazard(
const MachineInstr &MI) {
532 (!SOffset || !SOffset->
isReg()))
562 const int VALUWaitStates = 1;
563 int WaitStatesNeeded = 0;
566 return WaitStatesNeeded;
567 unsigned Reg = Def.
getReg();
569 int DataIdx = createsVALUHazard(*MI);
570 return DataIdx >= 0 &&
573 int WaitStatesNeededForDef =
574 VALUWaitStates - getWaitStatesSince(IsHazardFn);
575 WaitStatesNeeded =
std::max(WaitStatesNeeded, WaitStatesNeededForDef);
577 return WaitStatesNeeded;
587 int WaitStatesNeeded = 0;
590 WaitStatesNeeded =
std::max(WaitStatesNeeded, checkVALUHazardsHelper(Def, MRI));
593 return WaitStatesNeeded;
596 int GCNHazardRecognizer::checkInlineAsmHazards(
MachineInstr *IA) {
609 int WaitStatesNeeded = 0;
615 WaitStatesNeeded =
std::max(WaitStatesNeeded, checkVALUHazardsHelper(Op, MRI));
619 return WaitStatesNeeded;
622 int GCNHazardRecognizer::checkRWLaneHazards(
MachineInstr *RWLane) {
633 unsigned LaneSelectReg = LaneSelectOp->
getReg();
638 const int RWLaneWaitStates = 4;
639 int WaitStatesSince = getWaitStatesSinceDef(LaneSelectReg, IsHazardFn);
640 return RWLaneWaitStates - WaitStatesSince;
643 int GCNHazardRecognizer::checkRFEHazards(
MachineInstr *RFE) {
649 const int RFEWaitStates = 1;
654 int WaitStatesNeeded = getWaitStatesSinceSetReg(IsHazardFn);
655 return RFEWaitStates - WaitStatesNeeded;
658 int GCNHazardRecognizer::checkAnyInstHazards(
MachineInstr *MI) {
668 int MovFedWaitStates = 1;
669 int WaitStatesNeeded = 0;
675 return MI->
getOpcode() == AMDGPU::S_MOV_FED_B32;
677 int WaitStatesNeededForUse =
678 MovFedWaitStates - getWaitStatesSinceDef(
Use.getReg(), IsHazardFn);
679 WaitStatesNeeded =
std::max(WaitStatesNeeded, WaitStatesNeededForUse);
682 return WaitStatesNeeded;
685 int GCNHazardRecognizer::checkReadM0Hazards(
MachineInstr *MI) {
687 const int SMovRelWaitStates = 1;
691 return SMovRelWaitStates - getWaitStatesSinceDef(AMDGPU::M0, IsHazardFn);
static bool isSMovRel(unsigned Opcode)
Interface definition for SIRegisterInfo.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
AMDGPU specific subclass of TargetSubtarget.
This class represents lattice values for constants.
iterator_range< mop_iterator > uses()
Returns a range that includes all operands that are register uses.
bool hasReadM0MovRelInterpHazard() const
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
static bool isVINTRP(const MachineInstr &MI)
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
An efficient, type-erasing, non-owning reference to a callable.
static bool isRFE(unsigned Opcode)
const SIInstrInfo * getInstrInfo() const override
static void addRegUnits(const SIRegisterInfo &TRI, BitVector &BV, unsigned Reg)
unsigned const TargetRegisterInfo * TRI
static bool isSMRD(const MachineInstr &MI)
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
void EmitNoop() override
EmitNoop - This callback is invoked when a noop was added to the instruction stream.
static bool isDS(const MachineInstr &MI)
static bool isFLAT(const MachineInstr &MI)
const HexagonInstrInfo * TII
bool isAlwaysGDS(uint16_t Opcode) const
bool isSGPRReg(const MachineRegisterInfo &MRI, unsigned Reg) const
unsigned getNumOperands() const
Retuns the total number of operands.
static bool isMIMG(const MachineInstr &MI)
A Use represents the edge between a Value definition and its users.
bool hasSMovFedHazard() const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static bool isVALU(const MachineInstr &MI)
INLINEASM - Represents an inline asm block.
bool isVGPR(const MachineRegisterInfo &MRI, unsigned Reg) const
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
static bool isSendMsgTraceDataOrGDS(const SIInstrInfo &TII, const MachineInstr &MI)
static bool isMUBUF(const MachineInstr &MI)
static bool isSSetReg(unsigned Opcode)
LLVM_READONLY MachineOperand * getNamedOperand(MachineInstr &MI, unsigned OperandName) const
Returns the operand named Op.
unsigned PreEmitNoops(SUnit *SU) override
PreEmitNoops - This callback is invoked prior to emitting an instruction.
void RecedeCycle() override
RecedeCycle - This callback is invoked whenever the next bottom-up instruction to be scheduled cannot...
void EmitInstruction(SUnit *SU) override
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
unsigned MaxLookAhead
MaxLookAhead - Indicate the number of cycles in the scoreboard state.
static bool isDPP(const MachineInstr &MI)
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
static void addRegsToSet(const SIRegisterInfo &TRI, iterator_range< MachineInstr::const_mop_iterator > Ops, BitVector &Set)
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
unsigned const MachineRegisterInfo * MRI
unsigned getMaxLookAhead() const
bool anyCommon(const BitVector &RHS) const
Test if any common bits are set.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Generation getGeneration() const
bool isDebugInstr() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getNumWaitStates(const MachineInstr &MI) const
Return the number of wait states that result from executing this instruction.
static bool isSALU(const MachineInstr &MI)
HazardType getHazardType(SUnit *SU, int Stalls) override
getHazardType - Return the hazard type of emitting this node.
MachineOperand class - Representation of each machine instruction operand.
GCNHazardRecognizer(const MachineFunction &MF)
A range adaptor for a pair of iterators.
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
void AdvanceCycle() override
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
static bool isRWLane(unsigned Opcode)
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
bool none() const
none - Returns true if none of the bits are set.
Provides AMDGPU specific target descriptions.
Representation of each machine instruction.
Interface definition for SIInstrInfo.
static bool isMTBUF(const MachineInstr &MI)
bool has12DWordStoreHazard() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
int16_t RegClass
This specifies the register class enumeration of the operand if the operand is a register.
bool isXNACKEnabled() const
static bool isVMEM(const MachineInstr &MI)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isSGetReg(unsigned Opcode)
const MCOperandInfo * OpInfo
static unsigned getHWReg(const SIInstrInfo *TII, const MachineInstr &RegInstr)
const MachineOperand & getOperand(unsigned i) const
bool hasReadM0SendMsgHazard() const
bool isBufferSMRD(const MachineInstr &MI) const
Scheduling unit. This is a node in the scheduling DAG.
const SIRegisterInfo * getRegisterInfo() const override
static bool isDivFMas(unsigned Opcode)