mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-05 19:29:54 +00:00
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:
parent
827de0520e
commit
4e1fb18940
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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()) {
|
||||||
|
@ -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)) {
|
||||||
|
@ -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).
|
||||||
;
|
;
|
||||||
|
Loading…
Reference in New Issue
Block a user