33#define DEBUG_TYPE "scheduler"
37 cl::desc(
"Disable use of DFA during scheduling"));
41 cl::desc(
"Track reg pressure and switch priority to in-depth"));
44 : Picker(this), InstrItins(IS->MF->getSubtarget().getInstrItineraryData()) {
52 assert(ResourcesModel &&
"Unimplemented CreateTargetScheduleState.");
55 RegLimit.resize(NumRC);
56 RegPressure.resize(NumRC);
57 std::fill(RegLimit.begin(), RegLimit.end(), 0);
58 std::fill(RegPressure.begin(), RegPressure.end(), 0);
62 ParallelLiveRanges = 0;
63 HorizontalVerticalBalance = 0;
67ResourcePriorityQueue::numberRCValPredInSU(
SUnit *SU,
unsigned RCId) {
68 unsigned NumberDeps = 0;
92 for (
unsigned i = 0, e = ScegN->
getNumValues(); i != e; ++i) {
104unsigned ResourcePriorityQueue::numberRCValSuccInSU(
SUnit *SU,
106 unsigned NumberDeps = 0;
131 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
143 unsigned NumberDeps = 0;
152 unsigned NumberDeps = 0;
165 NumNodesSolelyBlocking.resize(SUnits->size(), 0);
167 for (
SUnit &SU : *SUnits) {
179 if (
LHS->isScheduleHigh && !
RHS->isScheduleHigh)
182 if (!
LHS->isScheduleHigh &&
RHS->isScheduleHigh)
185 unsigned LHSNum =
LHS->NodeNum;
186 unsigned RHSNum =
RHS->NodeNum;
191 if (LHSLatency < RHSLatency)
return true;
192 if (LHSLatency > RHSLatency)
return false;
198 if (LHSBlocked < RHSBlocked)
return true;
199 if (LHSBlocked > RHSBlocked)
return false;
203 return LHSNum < RHSNum;
209SUnit *ResourcePriorityQueue::getSingleUnscheduledPred(
SUnit *SU) {
210 SUnit *OnlyAvailablePred =
nullptr;
216 if (OnlyAvailablePred && OnlyAvailablePred != &PredSU)
218 OnlyAvailablePred = &PredSU;
221 return OnlyAvailablePred;
227 unsigned NumNodesBlocking = 0;
229 if (getSingleUnscheduledPred(Succ.
getSUnit()) == SU)
232 NumNodesSolelyBlocking[SU->
NodeNum] = NumNodesBlocking;
252 if (!ResourcesModel->canReserveResources(&TII->
get(
256 case TargetOpcode::EXTRACT_SUBREG:
257 case TargetOpcode::INSERT_SUBREG:
258 case TargetOpcode::SUBREG_TO_REG:
259 case TargetOpcode::REG_SEQUENCE:
260 case TargetOpcode::IMPLICIT_DEF:
266 for (
const SUnit *S : Packet)
267 for (
const SDep &Succ : S->Succs) {
285 ResourcesModel->clearResources();
292 ResourcesModel->reserveResources(&TII->
get(
295 case TargetOpcode::EXTRACT_SUBREG:
296 case TargetOpcode::INSERT_SUBREG:
297 case TargetOpcode::SUBREG_TO_REG:
298 case TargetOpcode::REG_SEQUENCE:
299 case TargetOpcode::IMPLICIT_DEF:
302 Packet.push_back(SU);
306 ResourcesModel->clearResources();
313 ResourcesModel->clearResources();
330 RegBalance += numberRCValSuccInSU(SU, RCId);
335 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
336 if (isa<ConstantSDNode>(
Op.getNode()))
341 RegBalance -= numberRCValPredInSU(SU, RCId);
364 if ((RegPressure[RC->getID()] +
366 (RegPressure[RC->getID()] +
434 if (
N->isMachineOpcode()) {
440 switch (
N->getOpcode()) {
463 ResourcesModel->clearResources();
473 for (
unsigned i = 0, e = ScegN->
getNumValues(); i != e; ++i) {
479 RegPressure[RC->
getID()] += numberRCValSuccInSU(SU, RC->
getID());
485 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
490 if (RegPressure[RC->
getID()] >
491 (numberRCValPredInSU(SU, RC->
getID())))
492 RegPressure[RC->
getID()] -= numberRCValPredInSU(SU, RC->
getID());
493 else RegPressure[RC->
getID()] = 0;
510 unsigned NumberNonControlDeps = 0;
513 adjustPriorityOfUnscheduledPreds(Succ.
getSUnit());
515 NumberNonControlDeps++;
518 if (!NumberNonControlDeps) {
519 if (ParallelLiveRanges >= SU->
NumPreds)
522 ParallelLiveRanges = 0;
534 unsigned NodeNumDefs = 0;
536 if (
N->isMachineOpcode()) {
539 if (
N->getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) {
543 NodeNumDefs = std::min(
N->getNumValues(), TID.
getNumDefs());
546 switch(
N->getOpcode()) {
566void ResourcePriorityQueue::adjustPriorityOfUnscheduledPreds(
SUnit *SU) {
569 SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU);
570 if (!OnlyAvailablePred || !OnlyAvailablePred->
isAvailable)
575 remove(OnlyAvailablePred);
579 push(OnlyAvailablePred);
589 std::vector<SUnit *>::iterator Best = Queue.begin();
592 for (
auto I = std::next(Queue.begin()), E = Queue.end();
I != E; ++
I) {
602 for (
auto I = std::next(Queue.begin()), E = Queue.end();
I != E; ++
I)
603 if (Picker(*Best, *
I))
608 if (Best != std::prev(Queue.end()))
618 assert(!Queue.empty() &&
"Queue is empty!");
619 std::vector<SUnit *>::iterator
I =
find(Queue, SU);
620 if (
I != std::prev(Queue.end()))
static const unsigned PriorityTwo
static const unsigned FactorOne
static const unsigned PriorityThree
static cl::opt< int > RegPressureThreshold("dfa-sched-reg-pressure-threshold", cl::Hidden, cl::init(5), cl::desc("Track reg pressure and switch priority to in-depth"))
static const unsigned ScaleOne
static unsigned numberCtrlPredInSU(SUnit *SU)
static const unsigned PriorityOne
static unsigned numberCtrlDepsInSU(SUnit *SU)
static cl::opt< bool > DisableDFASched("disable-dfa-sched", cl::Hidden, cl::desc("Disable use of DFA during scheduling"))
static const unsigned PriorityFour
static const unsigned ScaleTwo
static const unsigned ScaleThree
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file describes how to lower LLVM code to machine code.
This class represents an Operation in the Expression.
MCSchedModel SchedModel
Basic machine properties.
Describe properties that are true of each instruction in the target description file.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
bool isCall() const
Return true if the instruction is a call.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void push(SUnit *U) override
void scheduledNode(SUnit *SU) override
scheduledNode - Main resource tracking point.
ResourcePriorityQueue(SelectionDAGISel *IS)
void initNodes(std::vector< SUnit > &sunits) override
Initialize nodes.
unsigned getLatency(unsigned NodeNum) const
bool empty() const override
SUnit * pop() override
Main access point - returns next instructions to be placed in scheduling sequence.
int rawRegPressureDelta(SUnit *SU, unsigned RCId)
int regPressureDelta(SUnit *SU, bool RawPressure=false)
Estimates change in reg pressure from this SU.
void remove(SUnit *SU) override
unsigned getNumSolelyBlockNodes(unsigned NodeNum) const
void reserveResources(SUnit *SU)
Keep track of available resources.
int SUSchedulingCost(SUnit *SU)
Single cost function reflecting benefit of scheduling SU in the current cycle.
void initNumRegDefsLeft(SUnit *SU)
InitNumRegDefsLeft - Determine the # of regs defined by this node.
bool isResourceAvailable(SUnit *SU)
Check if scheduling of this SU is possible in the current packet.
Represents one node in the SelectionDAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
Scheduling unit. This is a node in the scheduling DAG.
unsigned NodeQueueId
Queue id of node.
unsigned NodeNum
Entry # of node in the node vector.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
unsigned short NumRegDefsLeft
bool isScheduleHigh
True if preferable to schedule high.
bool isScheduled
True once scheduled.
bool isAvailable
True once available.
SmallVector< SDep, 4 > Succs
All sunit successors.
SDNode * getNode() const
Returns the representative SDNode for this SUnit.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
const TargetLowering * TLI
virtual DFAPacketizer * CreateTargetScheduleState(const TargetSubtargetInfo &) const
Create machine specific model for scheduling.
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
unsigned getID() const
Return the register class ID number.
iterator_range< regclass_iterator > regclasses() const
unsigned getNumRegClasses() const
virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const
Return the register pressure "high water mark" for the specific register class.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ INLINEASM_BR
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ INLINEASM
INLINEASM - Represents an inline asm block.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool operator()(const SUnit *LHS, const SUnit *RHS) const
This heuristic is used if DFA scheduling is not desired for some VLIW platform.
ResourcePriorityQueue * PQ