25 #include "llvm/Config/llvm-config.h" 39 #define DEBUG_TYPE "pre-RA-sched" 44 cl::desc(
"Stress test instruction scheduling"));
47 void SchedulingPriorityQueue::anchor() {}
50 :
TM(mf.getTarget()),
TII(mf.getSubtarget().getInstrInfo()),
51 TRI(mf.getSubtarget().getRegisterInfo()), MF(mf),
52 MRI(mf.getRegInfo()) {
74 case Anti:
dbgs() <<
"Anti";
break;
75 case Output:
dbgs() <<
"Out ";
break;
76 case Order:
dbgs() <<
"Ord ";
break;
82 if (TRI && isAssignedRegDep())
91 switch(Contents.OrdKind) {
94 case MustAliasMem:
dbgs() <<
" Memory";
break;
95 case Artificial:
dbgs() <<
" Artificial";
break;
96 case Weak:
dbgs() <<
" Weak";
break;
97 case Cluster:
dbgs() <<
" Cluster";
break;
105 for (
SDep &PredDep : Preds) {
108 if (!Required && PredDep.getSUnit() == D.
getSUnit())
110 if (PredDep.overlaps(D)) {
114 SUnit *PredSU = PredDep.getSUnit();
116 SDep ForwardD = PredDep;
119 if (SuccDep == ForwardD) {
136 "NumPreds will overflow!");
138 "NumSuccs will overflow!");
148 "NumPredsLeft will overflow!");
158 "NumSuccsLeft will overflow!");
163 N->
Succs.push_back(P);
165 this->setDepthDirty();
174 if (I == Preds.
end())
181 assert(Succ != N->
Succs.end() &&
"Mismatching preds / succs lists!");
182 N->
Succs.erase(Succ);
186 assert(NumPreds > 0 &&
"NumPreds will underflow!");
195 assert(NumPredsLeft > 0 &&
"NumPredsLeft will underflow!");
207 if (
P.getLatency() != 0) {
208 this->setDepthDirty();
214 if (!isDepthCurrent)
return;
219 SU->isDepthCurrent =
false;
222 if (SuccSU->isDepthCurrent)
225 }
while (!WorkList.
empty());
229 if (!isHeightCurrent)
return;
234 SU->isHeightCurrent =
false;
237 if (PredSU->isHeightCurrent)
240 }
while (!WorkList.
empty());
244 if (NewDepth <= getDepth())
248 isDepthCurrent =
true;
252 if (NewHeight <= getHeight())
256 isHeightCurrent =
true;
260 void SUnit::ComputeDepth() {
267 unsigned MaxPredDepth = 0;
270 if (PredSU->isDepthCurrent)
271 MaxPredDepth =
std::max(MaxPredDepth,
281 if (MaxPredDepth != Cur->Depth) {
283 Cur->Depth = MaxPredDepth;
285 Cur->isDepthCurrent =
true;
287 }
while (!WorkList.
empty());
291 void SUnit::ComputeHeight() {
298 unsigned MaxSuccHeight = 0;
301 if (SuccSU->isHeightCurrent)
302 MaxSuccHeight =
std::max(MaxSuccHeight,
312 if (MaxSuccHeight != Cur->Height) {
314 Cur->Height = MaxSuccHeight;
316 Cur->isHeightCurrent =
true;
318 }
while (!WorkList.
empty());
326 unsigned MaxDepth = BestI->getSUnit()->getDepth();
332 if (BestI != Preds.begin())
336 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 338 dbgs() <<
" # preds left : " << NumPredsLeft <<
"\n";
339 dbgs() <<
" # succs left : " << NumSuccsLeft <<
"\n";
341 dbgs() <<
" # weak preds left : " << WeakPredsLeft <<
"\n";
343 dbgs() <<
" # weak succs left : " << WeakSuccsLeft <<
"\n";
344 dbgs() <<
" # rdefs left : " << NumRegDefsLeft <<
"\n";
346 dbgs() <<
" Depth : " << getDepth() <<
"\n";
347 dbgs() <<
" Height : " << getHeight() <<
"\n";
362 if (SU.
Preds.size() > 0) {
363 dbgs() <<
" Predecessors:\n";
372 if (SU.
Succs.size() > 0) {
373 dbgs() <<
" Successors:\n";
387 bool AnyNotSched =
false;
388 unsigned DeadNodes = 0;
396 dbgs() <<
"*** Scheduling failed! ***\n";
398 dbgs() <<
"has not been scheduled!\n";
405 dbgs() <<
"*** Scheduling failed! ***\n";
407 dbgs() <<
"has an unexpected " 408 << (isBottomUp ?
"Height" :
"Depth") <<
" value!\n";
414 dbgs() <<
"*** Scheduling failed! ***\n";
416 dbgs() <<
"has successors left!\n";
422 dbgs() <<
"*** Scheduling failed! ***\n";
424 dbgs() <<
"has predecessors left!\n";
430 return SUnits.size() - DeadNodes;
461 unsigned DAGSize =
SUnits.size();
462 std::vector<SUnit*> WorkList;
463 WorkList.reserve(DAGSize);
465 Index2Node.resize(DAGSize);
466 Node2Index.resize(DAGSize);
470 WorkList.push_back(
ExitSU);
472 int NodeNum = SU.NodeNum;
473 unsigned Degree = SU.Succs.size();
475 Node2Index[NodeNum] = Degree;
479 assert(SU.Succs.empty() &&
"SUnit should have no successors");
481 WorkList.push_back(&SU);
486 while (!WorkList.empty()) {
487 SUnit *SU = WorkList.back();
496 WorkList.push_back(SU);
500 Visited.resize(DAGSize);
504 for (
SUnit &SU : SUnits) {
505 for (
const SDep &
PD : SU.Preds) {
507 "Wrong topological sorting");
514 int UpperBound, LowerBound;
515 LowerBound = Node2Index[Y->
NodeNum];
516 UpperBound = Node2Index[X->
NodeNum];
517 bool HasLoop =
false;
519 if (LowerBound < UpperBound) {
522 DFS(Y, UpperBound, HasLoop);
523 assert(!HasLoop &&
"Inserted edge creates a loop!");
525 Shift(Visited, LowerBound, UpperBound);
533 void ScheduleDAGTopologicalSort::DFS(
const SUnit *SU,
int UpperBound,
535 std::vector<const SUnit*> WorkList;
536 WorkList.reserve(
SUnits.size());
538 WorkList.push_back(SU);
540 SU = WorkList.back();
543 for (
const SDep &SuccDep
545 unsigned s = SuccDep.getSUnit()->
NodeNum;
547 if (s >= Node2Index.size())
549 if (Node2Index[s] == UpperBound) {
554 if (!Visited.test(s) && Node2Index[s] < UpperBound) {
555 WorkList.push_back(SuccDep.getSUnit());
558 }
while (!WorkList.empty());
562 const SUnit &TargetSU,
564 std::vector<const SUnit*> WorkList;
565 int LowerBound = Node2Index[StartSU.
NodeNum];
566 int UpperBound = Node2Index[TargetSU.
NodeNum];
569 std::vector<int> Nodes;
571 if (LowerBound > UpperBound) {
576 WorkList.reserve(
SUnits.size());
581 WorkList.push_back(&StartSU);
583 const SUnit *SU = WorkList.back();
585 for (
int I = SU->
Succs.size()-1;
I >= 0; --
I) {
591 if (Node2Index[s] == UpperBound) {
596 if (!Visited.test(s) && Node2Index[s] < UpperBound) {
598 WorkList.push_back(Succ);
601 }
while (!WorkList.empty());
615 WorkList.push_back(&TargetSU);
617 const SUnit *SU = WorkList.back();
619 for (
int I = SU->
Preds.size()-1;
I >= 0; --
I) {
625 if (Node2Index[s] == LowerBound) {
629 if (!VisitedBack.
test(s) && Visited.test(s)) {
635 }
while (!WorkList.empty());
637 assert(Found &&
"Error in SUnit Graph!");
642 void ScheduleDAGTopologicalSort::Shift(
BitVector& Visited,
int LowerBound,
648 for (i = LowerBound; i <= UpperBound; ++i) {
650 int w = Index2Node[i];
651 if (Visited.
test(w)) {
657 Allocate(w, i - shift);
661 for (
unsigned LI : L) {
662 Allocate(LI, i - shift);
669 if (IsReachable(SU, TargetSU))
671 for (
const SDep &PredDep : TargetSU->
Preds)
673 IsReachable(SU, PredDep.
getSUnit()))
679 const SUnit *TargetSU) {
682 int UpperBound, LowerBound;
683 LowerBound = Node2Index[TargetSU->
NodeNum];
684 UpperBound = Node2Index[SU->
NodeNum];
685 bool HasLoop =
false;
687 if (LowerBound < UpperBound) {
690 DFS(TargetSU, UpperBound, HasLoop);
695 void ScheduleDAGTopologicalSort::Allocate(
int n,
int index) {
696 Node2Index[n] = index;
697 Index2Node[index] = n;
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
unsigned NumPreds
of SDep::Data preds.
This class represents lattice values for constants.
void push_back(const T &Elt)
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
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.
virtual void dumpNode(const SUnit &SU) const =0
virtual ~ScheduleHazardRecognizer()
bool test(unsigned Idx) const
unsigned const TargetRegisterInfo * TRI
void removePred(const SDep &D)
Removes the specified edge as a pred of the current node if it exists.
bool isAssignedRegDep() const
Tests if this is a Data dependence that is associated with a register.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
bool isScheduled
True once scheduled.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
SmallVectorImpl< SDep >::iterator pred_iterator
unsigned NumSuccs
of SDep::Data sucss.
unsigned getLatency() const
Returns the latency value for this edge, which roughly means the minimum number of cycles that must e...
unsigned NumSuccsLeft
of succs not scheduled.
const HexagonInstrInfo * TII
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Regular data dependence (aka true-dependence).
void InitDAGTopologicalSorting()
Creates the initial topological ordering from the DAG to be scheduled.
std::vector< int > GetSubGraph(const SUnit &StartSU, const SUnit &TargetSU, bool &Success)
Returns an array of SUs that are both in the successor subtree of StartSU and in the predecessor subt...
static cl::opt< bool > StressSchedOpt("stress-sched", cl::Hidden, cl::init(false), cl::desc("Stress test instruction scheduling"))
unsigned WeakSuccsLeft
of weak succs not scheduled.
unsigned NumPredsLeft
of preds not scheduled.
static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst)
Gets latency information for Inst, based on DC information.
bool isBoundaryNode() const
Boundary nodes are placeholders for the boundary of the scheduling region.
void dumpNodeAll(const SUnit &SU) const
void setDepthToAtLeast(unsigned NewDepth)
If NewDepth is greater than this node's depth value, sets it to be the new depth value.
void setHeightToAtLeast(unsigned NewHeight)
If NewDepth is greater than this node's depth value, set it to be the new height value.
initializer< Ty > init(const Ty &Val)
void setDepthDirty()
Sets a flag in this node to indicate that its stored Depth value will require recomputation the next ...
bool WillCreateCycle(SUnit *TargetSU, SUnit *SU)
Returns true if addPred(TargetSU, SU) creates a cycle.
unsigned const MachineRegisterInfo * MRI
void clearDAG()
Clears the DAG state (between regions).
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
void RemovePred(SUnit *M, SUnit *N)
Updates the topological ordering to accommodate an an edge to be removed from the specified node N fr...
void dumpNodeName(const SUnit &SU) const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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...
void dump(const TargetRegisterInfo *TRI=nullptr) const
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
LLVM_NODISCARD T pop_back_val()
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Represents one node in the SelectionDAG.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool IsReachable(const SUnit *SU, const SUnit *TargetSU)
Checks if SU is reachable from TargetSU.
void biasCriticalPath()
Orders this node's predecessor edges such that the critical path edge occurs first.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
ScheduleDAG(MachineFunction &mf)
typename SuperClass::iterator iterator
void setLatency(unsigned Lat)
Sets the latency for this edge.
SUnit EntrySU
Special node for the region entry.
unsigned VerifyScheduledDAG(bool isBottomUp)
Verifies that all SUnits were scheduled and that their state is consistent.
unsigned getHeight() const
Returns the height of this node, which is the length of the maximum path down to any node which has n...
SUnit ExitSU
Special node for the region exit.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
const TargetRegisterInfo * TRI
Target processor register info.
LLVM_NODISCARD bool empty() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
const TargetInstrInfo * TII
Target instruction information.
Kind getKind() const
Returns an enum value representing the kind of the dependence.
unsigned NodeNum
Entry # of node in the node vector.
void setHeightDirty()
Sets a flag in this node to indicate that its stored Height value will require recomputation the next...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
SmallVector< SDep, 4 > Succs
All sunit successors.
bool isWeak() const
Tests if this a weak dependence.
void AddPred(SUnit *Y, SUnit *X)
Updates the topological ordering to accommodate an edge to be added from SUnit X to SUnit Y...
std::vector< SUnit > SUnits
The scheduling units.
void dumpAttributes() const
ScheduleDAGTopologicalSort(std::vector< SUnit > &SUnits, SUnit *ExitSU)
Scheduling unit. This is a node in the scheduling DAG.