34 #define DEBUG_TYPE "scheduler" 38 cl::desc(
"Disable use of DFA during scheduling"));
42 cl::desc(
"Track reg pressure and switch priority to in-depth"));
45 : Picker(this), InstrItins(IS->MF->getSubtarget().getInstrItineraryData()) {
53 assert(ResourcesModel &&
"Unimplemented CreateTargetScheduleState.");
56 RegLimit.resize(NumRC);
57 RegPressure.resize(NumRC);
58 std::fill(RegLimit.begin(), RegLimit.end(), 0);
59 std::fill(RegPressure.begin(), RegPressure.end(), 0);
63 ParallelLiveRanges = 0;
64 HorizontalVerticalBalance = 0;
68 ResourcePriorityQueue::numberRCValPredInSU(
SUnit *SU,
unsigned RCId) {
69 unsigned NumberDeps = 0;
92 for (
unsigned i = 0, e = ScegN->
getNumValues(); i != e; ++i) {
104 unsigned ResourcePriorityQueue::numberRCValSuccInSU(
SUnit *SU,
106 unsigned NumberDeps = 0;
142 unsigned NumberDeps = 0;
151 unsigned NumberDeps = 0;
164 NumNodesSolelyBlocking.resize(SUnits->size(), 0);
166 for (
unsigned i = 0, e = SUnits->size(); i != e; ++i) {
167 SUnit *SU = &(*SUnits)[i];
185 unsigned LHSNum = LHS->
NodeNum;
186 unsigned RHSNum = RHS->
NodeNum;
189 unsigned LHSLatency = PQ->getLatency(LHSNum);
190 unsigned RHSLatency = PQ->getLatency(RHSNum);
191 if (LHSLatency < RHSLatency)
return true;
192 if (LHSLatency > RHSLatency)
return false;
196 unsigned LHSBlocked = PQ->getNumSolelyBlockNodes(LHSNum);
197 unsigned RHSBlocked = PQ->getNumSolelyBlockNodes(RHSNum);
198 if (LHSBlocked < RHSBlocked)
return true;
199 if (LHSBlocked > RHSBlocked)
return false;
203 return LHSNum < RHSNum;
209 SUnit *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 (
unsigned i = 0, e = Packet.size(); i != e; ++i)
267 for (
const SDep &Succ : Packet[i]->Succs) {
273 if (Succ.getSUnit() == SU)
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);
336 if (isa<ConstantSDNode>(Op.
getNode()))
341 RegBalance -= numberRCValPredInSU(SU, RCId);
364 if ((RegPressure[RC->getID()] +
366 (RegPressure[RC->getID()] +
409 ResCount <<= FactorOne;
425 ResCount <<= FactorOne;
434 if (
N->isMachineOpcode()) {
437 ResCount += (PriorityTwo + (ScaleThree*
N->getNumValues()));
440 switch (
N->getOpcode()) {
462 ResourcesModel->clearResources();
472 for (
unsigned i = 0, e = ScegN->
getNumValues(); i != e; ++i) {
478 RegPressure[RC->
getID()] += numberRCValSuccInSU(SU, RC->
getID());
489 if (RegPressure[RC->
getID()] >
490 (numberRCValPredInSU(SU, RC->
getID())))
491 RegPressure[RC->
getID()] -= numberRCValPredInSU(SU, RC->
getID());
492 else RegPressure[RC->
getID()] = 0;
509 unsigned NumberNonControlDeps = 0;
512 adjustPriorityOfUnscheduledPreds(Succ.
getSUnit());
514 NumberNonControlDeps++;
517 if (!NumberNonControlDeps) {
518 if (ParallelLiveRanges >= SU->
NumPreds)
521 ParallelLiveRanges = 0;
533 unsigned NodeNumDefs = 0;
535 if (
N->isMachineOpcode()) {
538 if (
N->getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) {
542 NodeNumDefs = std::min(
N->getNumValues(), TID.
getNumDefs());
545 switch(
N->getOpcode()) {
564 void ResourcePriorityQueue::adjustPriorityOfUnscheduledPreds(
SUnit *SU) {
567 SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU);
568 if (!OnlyAvailablePred || !OnlyAvailablePred->
isAvailable)
573 remove(OnlyAvailablePred);
577 push(OnlyAvailablePred);
587 std::vector<SUnit *>::iterator Best = Queue.begin();
590 for (
auto I = std::next(Queue.begin()),
E = Queue.end();
I !=
E; ++
I) {
600 for (
auto I = std::next(Queue.begin()),
E = Queue.end();
I !=
E; ++
I)
601 if (Picker(*Best, *
I))
606 if (Best != std::prev(Queue.end()))
616 assert(!Queue.empty() &&
"Queue is empty!");
617 std::vector<SUnit *>::iterator
I =
find(Queue, SU);
618 if (I != std::prev(Queue.end()))
static const unsigned PriorityTwo
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
static const unsigned PriorityFour
unsigned NumPreds
of SDep::Data preds.
This class represents lattice values for constants.
SDNode * getNode() const
Returns the representative SDNode for this SUnit.
static const unsigned ScaleTwo
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
Describe properties that are true of each instruction in the target description file.
bool empty() const override
virtual const TargetRegisterClass * getRegClassFor(MVT VT) const
Return the register class that should be used for the specified value type.
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static cl::opt< int > RegPressureThreshold("dfa-sched-reg-pressure-threshold", cl::Hidden, cl::ZeroOrMore, cl::init(5), cl::desc("Track reg pressure and switch priority to in-depth"))
SDNode * getNode() const
get the SDNode which holds the desired result
virtual unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const
Return the register pressure "high water mark" for the specific register class.
void reserveResources(SUnit *SU)
Keep track of available resources.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
static unsigned numberCtrlDepsInSU(SUnit *SU)
bool isScheduled
True once scheduled.
virtual DFAPacketizer * CreateTargetScheduleState(const TargetSubtargetInfo &) const
Create machine specific model for scheduling.
const TargetLowering * TLI
CopyToReg - This node has three operands: a chain, a register number to set to this value...
iterator_range< regclass_iterator > regclasses() const
void initNumRegDefsLeft(SUnit *SU)
InitNumRegDefsLeft - Determine the # of regs defined by this node.
unsigned getID() const
Return the register class ID number.
INLINEASM - Represents an inline asm block.
ResourcePriorityQueue(SelectionDAGISel *IS)
unsigned getNumRegClasses() const
bool isCtrl() const
Shorthand for getKind() != SDep::Data.
virtual const TargetInstrInfo * getInstrInfo() const
static const unsigned ScaleThree
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
initializer< Ty > init(const Ty &Val)
int rawRegPressureDelta(SUnit *SU, unsigned RCId)
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")
const SDValue & getOperand(unsigned Num) const
bool operator()(const SUnit *LHS, const SUnit *RHS) const
This heuristic is used if DFA scheduling is not desired for some VLIW platform.
int SUSchedulingCost(SUnit *SU)
Single cost function reflecting benefit of scheduling SU in the current cycle.
SDNode * getGluedNode() const
If this node has a glue operand, return the node to which the glue operand points.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
unsigned getNumOperands() const
Return the number of values used by this operation.
void remove(SUnit *SU) override
TokenFactor - This node takes multiple tokens as input and produces a single token result...
bool isScheduleHigh
True if preferable to schedule high.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isTypeLegal(EVT VT) const
Return true if the target has native support for the specified value type.
TargetSubtargetInfo - Generic base class for all target subtargets.
bool isAvailable
True once available.
unsigned NodeQueueId
Queue id of node.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
static const unsigned FactorOne
void scheduledNode(SUnit *SU) override
scheduledNode - Main resource tracking point.
MCSchedModel SchedModel
Basic machine properties.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
unsigned short NumRegDefsLeft
of reg defs with no scheduled use.
bool isCall() const
Return true if the instruction is a call.
static const unsigned PriorityThree
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
bool isResourceAvailable(SUnit *SU)
Check if scheduling of this SU is possible in the current packet.
static const unsigned PriorityOne
unsigned NodeNum
Entry # of node in the node vector.
static const unsigned ScaleOne
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void push(SUnit *U) override
unsigned getResNo() const
get the index which selects a specific result in the SDNode
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
SmallVector< SDep, 4 > Succs
All sunit successors.
SUnit * pop() override
Main access point - returns next instructions to be placed in scheduling sequence.
static unsigned numberCtrlPredInSU(SUnit *SU)
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
int regPressureDelta(SUnit *SU, bool RawPressure=false)
Estimates change in reg pressure from this SU.
void initNodes(std::vector< SUnit > &sunits) override
Initialize nodes.
static cl::opt< bool > DisableDFASched("disable-dfa-sched", cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::desc("Disable use of DFA during scheduling"))
Scheduling unit. This is a node in the scheduling DAG.
This file describes how to lower LLVM code to machine code.