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()) {
49 ResourcesModel.reset(TII->CreateTargetScheduleState(STI));
52 assert(ResourcesModel &&
"Unimplemented CreateTargetScheduleState.");
54 unsigned NumRC = TRI->getNumRegClasses();
55 RegLimit.resize(NumRC);
56 RegPressure.resize(NumRC);
60 RegLimit[RC->getID()] = TRI->getRegPressureLimit(RC, *IS->
MF);
62 ParallelLiveRanges = 0;
63 HorizontalVerticalBalance = 0;
69ResourcePriorityQueue::numberRCValPredInSU(
SUnit *SU,
unsigned RCId) {
70 unsigned NumberDeps = 0;
75 SUnit *PredSU = Pred.getSUnit();
88 case ISD::INLINEASM:
break;
89 case ISD::INLINEASM_BR:
break;
94 for (
unsigned i = 0, e = ScegN->
getNumValues(); i != e; ++i) {
106unsigned ResourcePriorityQueue::numberRCValSuccInSU(
SUnit *SU,
108 unsigned NumberDeps = 0;
109 for (
const SDep &Succ : SU->
Succs) {
114 const SDNode *ScegN = SuccSU->
getNode();
125 case ISD::INLINEASM:
break;
126 case ISD::INLINEASM_BR:
break;
133 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
134 if (TLI->isTypeLegal(VT)
135 && (TLI->getRegClassFor(VT)->getID() == RCId)) {
145 unsigned NumberDeps = 0;
154 unsigned NumberDeps = 0;
167 NumNodesSolelyBlocking.resize(SUnits->size(), 0);
169 for (
SUnit &SU : *SUnits) {
181 if (LHS->isScheduleHigh && !RHS->isScheduleHigh)
184 if (!LHS->isScheduleHigh && RHS->isScheduleHigh)
187 unsigned LHSNum = LHS->NodeNum;
188 unsigned RHSNum = RHS->NodeNum;
191 unsigned LHSLatency =
PQ->getLatency(LHSNum);
192 unsigned RHSLatency =
PQ->getLatency(RHSNum);
193 if (LHSLatency < RHSLatency)
return true;
194 if (LHSLatency > RHSLatency)
return false;
198 unsigned LHSBlocked =
PQ->getNumSolelyBlockNodes(LHSNum);
199 unsigned RHSBlocked =
PQ->getNumSolelyBlockNodes(RHSNum);
200 if (LHSBlocked < RHSBlocked)
return true;
201 if (LHSBlocked > RHSBlocked)
return false;
205 return LHSNum < RHSNum;
211SUnit *ResourcePriorityQueue::getSingleUnscheduledPred(
SUnit *SU) {
212 SUnit *OnlyAvailablePred =
nullptr;
214 SUnit &PredSU = *Pred.getSUnit();
218 if (OnlyAvailablePred && OnlyAvailablePred != &PredSU)
220 OnlyAvailablePred = &PredSU;
223 return OnlyAvailablePred;
229 unsigned NumNodesBlocking = 0;
231 if (getSingleUnscheduledPred(Succ.
getSUnit()) == SU)
234 NumNodesSolelyBlocking[SU->
NodeNum] = NumNodesBlocking;
254 if (!ResourcesModel->canReserveResources(&TII->get(
258 case TargetOpcode::EXTRACT_SUBREG:
259 case TargetOpcode::INSERT_SUBREG:
260 case TargetOpcode::SUBREG_TO_REG:
261 case TargetOpcode::REG_SEQUENCE:
262 case TargetOpcode::IMPLICIT_DEF:
268 for (
const SUnit *S : Packet)
269 for (
const SDep &Succ : S->Succs) {
287 ResourcesModel->clearResources();
294 ResourcesModel->reserveResources(&TII->get(
297 case TargetOpcode::EXTRACT_SUBREG:
298 case TargetOpcode::INSERT_SUBREG:
299 case TargetOpcode::SUBREG_TO_REG:
300 case TargetOpcode::REG_SEQUENCE:
301 case TargetOpcode::IMPLICIT_DEF:
304 Packet.push_back(SU);
308 ResourcesModel->clearResources();
314 if (Packet.size() >= InstrItins->SchedModel.IssueWidth) {
315 ResourcesModel->clearResources();
329 if (TLI->isTypeLegal(VT)
330 && TLI->getRegClassFor(VT)
331 && TLI->getRegClassFor(VT)->getID() == RCId)
332 RegBalance += numberRCValSuccInSU(SU, RCId);
337 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
341 if (TLI->isTypeLegal(VT) && TLI->getRegClassFor(VT)
342 && TLI->getRegClassFor(VT)->getID() == RCId)
343 RegBalance -= numberRCValPredInSU(SU, RCId);
366 if ((RegPressure[RC->getID()] +
368 (RegPressure[RC->getID()] +
436 if (
N->isMachineOpcode()) {
437 const MCInstrDesc &TID = TII->get(
N->getMachineOpcode());
442 switch (
N->getOpcode()) {
451 case ISD::INLINEASM_BR:
465 ResourcesModel->clearResources();
475 for (
unsigned i = 0, e = ScegN->
getNumValues(); i != e; ++i) {
478 if (TLI->isTypeLegal(VT)) {
481 RegPressure[RC->
getID()] += numberRCValSuccInSU(SU, RC->
getID());
487 MVT VT =
Op.getNode()->getSimpleValueType(
Op.getResNo());
489 if (TLI->isTypeLegal(VT)) {
492 if (RegPressure[RC->
getID()] >
493 (numberRCValPredInSU(SU, RC->
getID())))
494 RegPressure[RC->
getID()] -= numberRCValPredInSU(SU, RC->
getID());
495 else RegPressure[RC->
getID()] = 0;
500 if (Pred.isCtrl() || (Pred.getSUnit()->NumRegDefsLeft == 0))
502 --Pred.getSUnit()->NumRegDefsLeft;
512 unsigned NumberNonControlDeps = 0;
515 adjustPriorityOfUnscheduledPreds(Succ.
getSUnit());
517 NumberNonControlDeps++;
520 if (!NumberNonControlDeps) {
521 if (ParallelLiveRanges >= SU->
NumPreds)
524 ParallelLiveRanges = 0;
536 unsigned NodeNumDefs = 0;
538 if (
N->isMachineOpcode()) {
539 const MCInstrDesc &TID = TII->get(
N->getMachineOpcode());
541 if (
N->getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) {
545 NodeNumDefs = std::min(
N->getNumValues(), TID.
getNumDefs());
548 switch(
N->getOpcode()) {
554 case ISD::INLINEASM_BR:
568void ResourcePriorityQueue::adjustPriorityOfUnscheduledPreds(
SUnit *SU) {
571 SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU);
572 if (!OnlyAvailablePred || !OnlyAvailablePred->
isAvailable)
577 remove(OnlyAvailablePred);
581 push(OnlyAvailablePred);
591 std::vector<SUnit *>::iterator Best = Queue.begin();
594 for (
auto I = std::next(Queue.begin()), E = Queue.end();
I != E; ++
I) {
604 for (
auto I = std::next(Queue.begin()), E = Queue.end();
I != E; ++
I)
605 if (Picker(*Best, *
I))
610 if (Best != std::prev(Queue.end()))
620 assert(!Queue.empty() &&
"Queue is empty!");
621 std::vector<SUnit *>::iterator
I =
find(Queue, SU);
622 if (
I != std::prev(Queue.end()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
This file describes how to lower LLVM code to machine code.
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 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.
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
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 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.
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
@ 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,...
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
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 fill(R &&Range, T &&Value)
Provide wrappers to std::fill which take ranges instead of having to pass begin/end explicitly.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
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