28 #define DEBUG_TYPE "pre-RA-sched"
33 cl::desc(
"Stress test instruction scheduling"));
36 void SchedulingPriorityQueue::anchor() { }
39 :
TM(mf.getTarget()),
TII(mf.getSubtarget().getInstrInfo()),
40 TRI(mf.getSubtarget().getRegisterInfo()), MF(mf),
41 MRI(mf.getRegInfo()), EntrySU(), ExitSU() {
71 if (!Required &&
I->getSUnit() == D.
getSUnit())
76 SUnit *PredSU =
I->getSUnit();
81 EE = PredSU->
Succs.end(); II != EE; ++II) {
82 if (*II == ForwardD) {
122 N->
Succs.push_back(P);
143 assert(Succ != N->
Succs.end() &&
"Mismatching preds / succs lists!");
144 N->
Succs.erase(Succ);
169 if (
P.getLatency() != 0) {
177 void SUnit::setDepthDirty() {
178 if (!isDepthCurrent)
return;
183 SU->isDepthCurrent =
false;
186 SUnit *SuccSU =
I->getSUnit();
187 if (SuccSU->isDepthCurrent)
190 }
while (!WorkList.
empty());
194 if (!isHeightCurrent)
return;
199 SU->isHeightCurrent =
false;
202 SUnit *PredSU =
I->getSUnit();
203 if (PredSU->isHeightCurrent)
206 }
while (!WorkList.
empty());
217 isDepthCurrent =
true;
228 isHeightCurrent =
true;
233 void SUnit::ComputeDepth() {
240 unsigned MaxPredDepth = 0;
243 SUnit *PredSU =
I->getSUnit();
244 if (PredSU->isDepthCurrent)
245 MaxPredDepth = std::max(MaxPredDepth,
246 PredSU->Depth +
I->getLatency());
255 if (MaxPredDepth != Cur->Depth) {
257 Cur->Depth = MaxPredDepth;
259 Cur->isDepthCurrent =
true;
261 }
while (!WorkList.
empty());
266 void SUnit::ComputeHeight() {
273 unsigned MaxSuccHeight = 0;
276 SUnit *SuccSU =
I->getSUnit();
277 if (SuccSU->isHeightCurrent)
278 MaxSuccHeight = std::max(MaxSuccHeight,
279 SuccSU->Height +
I->getLatency());
288 if (MaxSuccHeight != Cur->Height) {
290 Cur->Height = MaxSuccHeight;
292 Cur->isHeightCurrent =
true;
294 }
while (!WorkList.
empty());
302 unsigned MaxDepth = BestI->getSUnit()->getDepth();
308 if (BestI !=
Preds.begin())
312 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
316 else if (
this == &DAG->
EntrySU)
344 if (
Preds.size() != 0) {
345 dbgs() <<
" Predecessors:\n";
349 switch (
I->getKind()) {
355 I->getSUnit()->print(
dbgs(), G);
356 if (
I->isArtificial())
358 dbgs() <<
": Latency=" <<
I->getLatency();
359 if (
I->isAssignedRegDep())
364 if (
Succs.size() != 0) {
365 dbgs() <<
" Successors:\n";
369 switch (
I->getKind()) {
375 I->getSUnit()->print(
dbgs(), G);
376 if (
I->isArtificial())
378 dbgs() <<
": Latency=" <<
I->getLatency();
379 if (
I->isAssignedRegDep())
392 bool AnyNotSched =
false;
393 unsigned DeadNodes = 0;
394 for (
unsigned i = 0, e =
SUnits.size();
i != e; ++
i) {
401 dbgs() <<
"*** Scheduling failed! ***\n";
403 dbgs() <<
"has not been scheduled!\n";
410 dbgs() <<
"*** Scheduling failed! ***\n";
412 dbgs() <<
"has an unexpected "
413 << (isBottomUp ?
"Height" :
"Depth") <<
" value!\n";
417 if (
SUnits[
i].NumSuccsLeft != 0) {
419 dbgs() <<
"*** Scheduling failed! ***\n";
421 dbgs() <<
"has successors left!\n";
425 if (
SUnits[
i].NumPredsLeft != 0) {
427 dbgs() <<
"*** Scheduling failed! ***\n";
429 dbgs() <<
"has predecessors left!\n";
435 return SUnits.size() - DeadNodes;
469 unsigned DAGSize = SUnits.size();
470 std::vector<SUnit*> WorkList;
473 Index2Node.resize(DAGSize);
474 Node2Index.resize(DAGSize);
478 WorkList.push_back(ExitSU);
479 for (
unsigned i = 0, e = DAGSize;
i != e; ++
i) {
482 unsigned Degree = SU->
Succs.size();
484 Node2Index[NodeNum] = Degree;
488 assert(SU->
Succs.empty() &&
"SUnit should have no successors");
490 WorkList.push_back(SU);
495 while (!WorkList.empty()) {
496 SUnit *SU = WorkList.back();
502 SUnit *SU =
I->getSUnit();
506 WorkList.push_back(SU);
514 for (
unsigned i = 0, e = DAGSize;
i != e; ++
i) {
518 assert(Node2Index[SU->
NodeNum] > Node2Index[
I->getSUnit()->NodeNum] &&
519 "Wrong topological sorting");
528 int UpperBound, LowerBound;
529 LowerBound = Node2Index[Y->
NodeNum];
530 UpperBound = Node2Index[X->
NodeNum];
531 bool HasLoop =
false;
533 if (LowerBound < UpperBound) {
536 DFS(Y, UpperBound, HasLoop);
537 assert(!HasLoop &&
"Inserted edge creates a loop!");
539 Shift(Visited, LowerBound, UpperBound);
553 void ScheduleDAGTopologicalSort::DFS(
const SUnit *SU,
int UpperBound,
555 std::vector<const SUnit*> WorkList;
556 WorkList.
reserve(SUnits.size());
558 WorkList.push_back(SU);
560 SU = WorkList.back();
563 for (
int I = SU->
Succs.size()-1;
I >= 0; --
I) {
564 unsigned s = SU->
Succs[
I].getSUnit()->NodeNum;
566 if (s >= Node2Index.size())
568 if (Node2Index[s] == UpperBound) {
573 if (!Visited.
test(s) && Node2Index[s] < UpperBound) {
574 WorkList.push_back(SU->
Succs[
I].getSUnit());
577 }
while (!WorkList.empty());
582 void ScheduleDAGTopologicalSort::Shift(
BitVector& Visited,
int LowerBound,
588 for (i = LowerBound; i <= UpperBound; ++
i) {
590 int w = Index2Node[
i];
591 if (Visited.
test(w)) {
597 Allocate(w, i - shift);
601 for (
unsigned j = 0; j < L.size(); ++j) {
602 Allocate(L[j], i - shift);
616 if (
I->isAssignedRegDep() &&
624 const SUnit *TargetSU) {
627 int UpperBound, LowerBound;
628 LowerBound = Node2Index[TargetSU->
NodeNum];
629 UpperBound = Node2Index[SU->
NodeNum];
630 bool HasLoop =
false;
632 if (LowerBound < UpperBound) {
635 DFS(TargetSU, UpperBound, HasLoop);
641 void ScheduleDAGTopologicalSort::Allocate(
int n,
int index) {
642 Node2Index[n] = index;
643 Index2Node[index] = n;
648 : SUnits(sunits), ExitSU(exitsu) {}
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
void push_back(const T &Elt)
void print(raw_ostream &O, const ScheduleDAG *G) const
Describe properties that are true of each instruction in the target description file.
virtual ~ScheduleHazardRecognizer()
void removePred(const SDep &D)
removePred - This removes the specified edge as a pred of the current node if it exists.
void reserve(size_type N)
SmallVector< SDep, 4 > Preds
A register anti-dependedence (aka WAR).
void dumpAll(const ScheduleDAG *G) const
unsigned getHeight() const
getHeight - Return the height of this node, which is the length of the maximum path down to any node ...
bool isWeak() const
isWeak - Test if this a weak dependence.
const HexagonInstrInfo * TII
Kind getKind() const
getKind - Return an enum value representing the kind of the dependence.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
Regular data dependence (aka true-dependence).
void InitDAGTopologicalSorting()
InitDAGTopologicalSorting - create the initial topological ordering from the DAG to be scheduled...
LLVM_NODISCARD bool empty() const
A register output-dependence (aka WAW).
static cl::opt< bool > StressSchedOpt("stress-sched", cl::Hidden, cl::init(false), cl::desc("Stress test instruction scheduling"))
Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubRegIdx=0)
Prints virtual and physical registers with or without a TRI instance.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
void setDepthToAtLeast(unsigned NewDepth)
setDepthToAtLeast - If NewDepth is greater than this node's depth value, set it to be the new depth v...
SDep - Scheduling dependency.
void setHeightToAtLeast(unsigned NewHeight)
setDepthToAtLeast - If NewDepth is greater than this node's depth value, set it to be the new height ...
initializer< Ty > init(const Ty &Val)
void setDepthDirty()
setDepthDirty - Set a flag in this node to indicate that its stored Depth value will require recomput...
bool WillCreateCycle(SUnit *TargetSU, SUnit *SU)
WillCreateCycle - Return true if addPred(TargetSU, SU) creates a cycle.
unsigned const MachineRegisterInfo * MRI
void clearDAG()
clearDAG - clear the DAG state (between regions).
unsigned getLatency() const
getLatency - Return the latency value for this edge, which roughly means the minimum number of cycles...
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
void RemovePred(SUnit *M, SUnit *N)
RemovePred - Updates the topological ordering to accommodate an an edge to be removed from the specif...
Any other ordering dependency.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
auto find(R &&Range, const T &Val) -> decltype(std::begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool test(unsigned Idx) const
LLVM_NODISCARD T pop_back_val()
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)
IsReachable - Checks if SU is reachable from TargetSU.
void biasCriticalPath()
Order this node's predecessor edges such that the critical path edge occurs first.
ScheduleDAG(MachineFunction &mf)
unsigned getDepth() const
getDepth - Return the depth of this node, which is the length of the maximum path up to any node whic...
unsigned VerifyScheduledDAG(bool isBottomUp)
VerifyScheduledDAG - Verify that all SUnits were scheduled and that their state is consistent...
const TargetRegisterInfo * TRI
unsigned short NumRegDefsLeft
const TargetInstrInfo * TII
void setHeightDirty()
setHeightDirty - Set a flag in this node to indicate that its stored Height value will require recomp...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
virtual void dumpNode(const SUnit *SU) const =0
bool addPred(const SDep &D, bool Required=true)
addPred - This adds the specified edge as a pred of the current node if not already.
SmallVector< SDep, 4 > Succs
This class implements an extremely fast bulk output stream that can only output to a stream...
void AddPred(SUnit *Y, SUnit *X)
AddPred - Updates the topological ordering to accommodate an edge to be added from SUnit X to SUnit Y...
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
std::vector< SUnit > SUnits
ScheduleDAGTopologicalSort(std::vector< SUnit > &SUnits, SUnit *ExitSU)
void dump(const ScheduleDAG *G) const
SUnit - Scheduling unit.
SUnit - Scheduling unit. This is a node in the scheduling DAG.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.