MIsched: Improve the interface to SchedDFS analysis (subtrees).

Allow the strategy to select SchedDFS. Allow the results of SchedDFS
to affect initialization of the scheduler state.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173425 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Andrew Trick 2013-01-25 06:33:57 +00:00
parent 827de0520e
commit 4e1fb18940
6 changed files with 61 additions and 47 deletions

View File

@ -316,12 +316,9 @@ public:
const SUnit *getNextClusterSucc() const { return NextClusterSucc; } const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
/// Initialize a DFSResult after DAG building is complete, and before any /// Compute a DFSResult after DAG building is complete, and before any
/// queue comparisons. /// queue comparisons.
void initDFSResult(); void computeDFSResult();
/// Compute DFS result once all interesting roots are discovered.
void computeDFSResult(ArrayRef<SUnit*> Roots);
/// Return a non-null DFS result if the scheduling strategy initialized it. /// Return a non-null DFS result if the scheduling strategy initialized it.
const SchedDFSResult *getDFSResult() const { return DFSResult; } const SchedDFSResult *getDFSResult() const { return DFSResult; }
@ -341,8 +338,8 @@ protected:
/// instances of ScheduleDAGMI to perform custom DAG postprocessing. /// instances of ScheduleDAGMI to perform custom DAG postprocessing.
void postprocessDAG(); void postprocessDAG();
/// Identify DAG roots and setup scheduler queues. /// Release ExitSU predecessors and setup scheduler queues.
void initQueues(); void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
/// Move an instruction and update register pressure. /// Move an instruction and update register pressure.
void scheduleMI(SUnit *SU, bool IsTopNode); void scheduleMI(SUnit *SU, bool IsTopNode);
@ -365,7 +362,8 @@ protected:
void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
bool checkSchedLimit(); bool checkSchedLimit();
void releaseRoots(); void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
SmallVectorImpl<SUnit*> &BotRoots);
void releaseSucc(SUnit *SU, SDep *SuccEdge); void releaseSucc(SUnit *SU, SDep *SuccEdge);
void releaseSuccessors(SUnit *SU); void releaseSuccessors(SUnit *SU);

View File

@ -127,7 +127,7 @@ public:
} }
/// \brief Compute various metrics for the DAG with given roots. /// \brief Compute various metrics for the DAG with given roots.
void compute(ArrayRef<SUnit *> Roots); void compute(ArrayRef<SUnit> SUnits);
/// \brief Get the ILP value for a DAG node. /// \brief Get the ILP value for a DAG node.
/// ///
@ -140,7 +140,12 @@ public:
unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); } unsigned getNumSubtrees() const { return SubtreeConnectLevels.size(); }
/// \brief Get the ID of the subtree the given DAG node belongs to. /// \brief Get the ID of the subtree the given DAG node belongs to.
///
/// For convenience, if DFSResults have not been computed yet, give everything
/// tree ID 0.
unsigned getSubtreeID(const SUnit *SU) const { unsigned getSubtreeID(const SUnit *SU) const {
if (empty())
return 0;
assert(SU->NodeNum < DFSData.size() && "New Node"); assert(SU->NodeNum < DFSData.size() && "New Node");
return DFSData[SU->NodeNum].SubtreeID; return DFSData[SU->NodeNum].SubtreeID;
} }

View File

@ -510,10 +510,19 @@ void ScheduleDAGMI::schedule() {
postprocessDAG(); postprocessDAG();
SmallVector<SUnit*, 8> TopRoots, BotRoots;
findRootsAndBiasEdges(TopRoots, BotRoots);
// Initialize the strategy before modifying the DAG.
// This may initialize a DFSResult to be used for queue priority.
SchedImpl->initialize(this);
DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
SUnits[su].dumpAll(this)); SUnits[su].dumpAll(this));
if (ViewMISchedDAGs) viewGraph();
initQueues(); // Initialize ready queues now that the DAG and priority data are finalized.
initQueues(TopRoots, BotRoots);
bool IsTopNode = false; bool IsTopNode = false;
while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) { while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) {
@ -561,25 +570,18 @@ void ScheduleDAGMI::postprocessDAG() {
} }
} }
void ScheduleDAGMI::initDFSResult() { void ScheduleDAGMI::computeDFSResult() {
if (!DFSResult) if (!DFSResult)
DFSResult = new SchedDFSResult(/*BottomU*/true, MinSubtreeSize); DFSResult = new SchedDFSResult(/*BottomU*/true, MinSubtreeSize);
DFSResult->clear(); DFSResult->clear();
DFSResult->resize(SUnits.size());
ScheduledTrees.clear(); ScheduledTrees.clear();
} DFSResult->resize(SUnits.size());
DFSResult->compute(SUnits);
void ScheduleDAGMI::computeDFSResult(ArrayRef<SUnit*> Roots) {
DFSResult->compute(Roots);
ScheduledTrees.resize(DFSResult->getNumSubtrees()); ScheduledTrees.resize(DFSResult->getNumSubtrees());
} }
// Release all DAG roots for scheduling. void ScheduleDAGMI::findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
// SmallVectorImpl<SUnit*> &BotRoots) {
// Nodes with unreleased weak edges can still be roots.
void ScheduleDAGMI::releaseRoots() {
SmallVector<SUnit*, 16> BotRoots;
for (std::vector<SUnit>::iterator for (std::vector<SUnit>::iterator
I = SUnits.begin(), E = SUnits.end(); I != E; ++I) { I = SUnits.begin(), E = SUnits.end(); I != E; ++I) {
SUnit *SU = &(*I); SUnit *SU = &(*I);
@ -589,28 +591,33 @@ void ScheduleDAGMI::releaseRoots() {
// A SUnit is ready to top schedule if it has no predecessors. // A SUnit is ready to top schedule if it has no predecessors.
if (!I->NumPredsLeft && SU != &EntrySU) if (!I->NumPredsLeft && SU != &EntrySU)
SchedImpl->releaseTopNode(SU); TopRoots.push_back(SU);
// A SUnit is ready to bottom schedule if it has no successors. // A SUnit is ready to bottom schedule if it has no successors.
if (!I->NumSuccsLeft && SU != &ExitSU) if (!I->NumSuccsLeft && SU != &ExitSU)
BotRoots.push_back(SU); BotRoots.push_back(SU);
} }
// Release bottom roots in reverse order so the higher priority nodes appear
// first. This is more natural and slightly more efficient.
for (SmallVectorImpl<SUnit*>::const_reverse_iterator
I = BotRoots.rbegin(), E = BotRoots.rend(); I != E; ++I)
SchedImpl->releaseBottomNode(*I);
} }
/// Identify DAG roots and setup scheduler queues. /// Identify DAG roots and setup scheduler queues.
void ScheduleDAGMI::initQueues() { void ScheduleDAGMI::initQueues(ArrayRef<SUnit*> TopRoots,
ArrayRef<SUnit*> BotRoots) {
NextClusterSucc = NULL; NextClusterSucc = NULL;
NextClusterPred = NULL; NextClusterPred = NULL;
// Initialize the strategy before modifying the DAG.
SchedImpl->initialize(this);
// Release all DAG roots for scheduling, not including EntrySU/ExitSU. // Release all DAG roots for scheduling, not including EntrySU/ExitSU.
releaseRoots(); //
// Nodes with unreleased weak edges can still be roots.
// Release top roots in forward order.
for (SmallVectorImpl<SUnit*>::const_iterator
I = TopRoots.begin(), E = TopRoots.end(); I != E; ++I) {
SchedImpl->releaseTopNode(*I);
}
// Release bottom roots in reverse order so the higher priority nodes appear
// first. This is more natural and slightly more efficient.
for (SmallVectorImpl<SUnit*>::const_reverse_iterator
I = BotRoots.rbegin(), E = BotRoots.rend(); I != E; ++I) {
SchedImpl->releaseBottomNode(*I);
}
releaseSuccessors(&EntrySU); releaseSuccessors(&EntrySU);
releasePredecessors(&ExitSU); releasePredecessors(&ExitSU);
@ -1216,7 +1223,7 @@ void ConvergingScheduler::initialize(ScheduleDAGMI *dag) {
Top.init(DAG, SchedModel, &Rem); Top.init(DAG, SchedModel, &Rem);
Bot.init(DAG, SchedModel, &Rem); Bot.init(DAG, SchedModel, &Rem);
DAG->initDFSResult(); DAG->computeDFSResult();
// Initialize resource counts. // Initialize resource counts.
@ -1278,8 +1285,6 @@ void ConvergingScheduler::registerRoots() {
Rem.CriticalPath = (*I)->getDepth(); Rem.CriticalPath = (*I)->getDepth();
} }
DEBUG(dbgs() << "Critical Path: " << Rem.CriticalPath << '\n'); DEBUG(dbgs() << "Critical Path: " << Rem.CriticalPath << '\n');
DAG->computeDFSResult(Bot.Available.elements());
} }
/// Does this SU have a hazard within the current instruction group. /// Does this SU have a hazard within the current instruction group.
@ -2140,14 +2145,13 @@ public:
virtual void initialize(ScheduleDAGMI *dag) { virtual void initialize(ScheduleDAGMI *dag) {
DAG = dag; DAG = dag;
DAG->initDFSResult(); DAG->computeDFSResult();
Cmp.DFSResult = DAG->getDFSResult(); Cmp.DFSResult = DAG->getDFSResult();
Cmp.ScheduledTrees = &DAG->getScheduledTrees(); Cmp.ScheduledTrees = &DAG->getScheduledTrees();
ReadyQ.clear(); ReadyQ.clear();
} }
virtual void registerRoots() { virtual void registerRoots() {
DAG->computeDFSResult(ReadyQ);
// Restore the heap in ReadyQ with the updated DFS results. // Restore the heap in ReadyQ with the updated DFS results.
std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp); std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
} }

View File

@ -1188,16 +1188,20 @@ static bool hasDataSucc(const SUnit *SU) {
/// Compute an ILP metric for all nodes in the subDAG reachable via depth-first /// Compute an ILP metric for all nodes in the subDAG reachable via depth-first
/// search from this root. /// search from this root.
void SchedDFSResult::compute(ArrayRef<SUnit *> Roots) { void SchedDFSResult::compute(ArrayRef<SUnit> SUnits) {
if (!IsBottomUp) if (!IsBottomUp)
llvm_unreachable("Top-down ILP metric is unimplemnted"); llvm_unreachable("Top-down ILP metric is unimplemnted");
SchedDFSImpl Impl(*this); SchedDFSImpl Impl(*this);
for (ArrayRef<const SUnit*>::const_iterator for (ArrayRef<SUnit>::const_iterator
RootI = Roots.begin(), RootE = Roots.end(); RootI != RootE; ++RootI) { SI = SUnits.begin(), SE = SUnits.end(); SI != SE; ++SI) {
const SUnit *SU = &*SI;
if (Impl.isVisited(SU) || hasDataSucc(SU))
continue;
SchedDAGReverseDFS DFS; SchedDAGReverseDFS DFS;
Impl.visitPreorder(*RootI); Impl.visitPreorder(SU);
DFS.follow(*RootI); DFS.follow(SU);
for (;;) { for (;;) {
// Traverse the leftmost path as far as possible. // Traverse the leftmost path as far as possible.
while (DFS.getPred() != DFS.getPredEnd()) { while (DFS.getPred() != DFS.getPredEnd()) {

View File

@ -152,6 +152,12 @@ void VLIWMachineScheduler::schedule() {
// Postprocess the DAG to add platform specific artificial dependencies. // Postprocess the DAG to add platform specific artificial dependencies.
postprocessDAG(); postprocessDAG();
SmallVector<SUnit*, 8> TopRoots, BotRoots;
findRootsAndBiasEdges(TopRoots, BotRoots);
// Initialize the strategy before modifying the DAG.
SchedImpl->initialize(this);
// To view Height/Depth correctly, they should be accessed at least once. // To view Height/Depth correctly, they should be accessed at least once.
DEBUG(unsigned maxH = 0; DEBUG(unsigned maxH = 0;
for (unsigned su = 0, e = SUnits.size(); su != e; ++su) for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
@ -166,7 +172,7 @@ void VLIWMachineScheduler::schedule() {
DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su) DEBUG(for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
SUnits[su].dumpAll(this)); SUnits[su].dumpAll(this));
initQueues(); initQueues(TopRoots, BotRoots);
bool IsTopNode = false; bool IsTopNode = false;
while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) { while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) {

View File

@ -8,9 +8,6 @@
; RUN: -misched=ilpmax -verify-machineinstrs \ ; RUN: -misched=ilpmax -verify-machineinstrs \
; RUN: | FileCheck %s -check-prefix=ILPMAX ; RUN: | FileCheck %s -check-prefix=ILPMAX
; ;
; Very temporary xfail during SchedDFSResult churn.
; XFAIL: *
;
; Verify that the MI scheduler minimizes register pressure for a ; Verify that the MI scheduler minimizes register pressure for a
; uniform set of bottom-up subtrees (unrolled matrix multiply). ; uniform set of bottom-up subtrees (unrolled matrix multiply).
; ;