mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-11 07:18:44 +00:00
MISched: Add SchedDFSResult to ScheduleDAGMI to formalize the
interface and allow other strategies to select it. llvm-svn: 173413
This commit is contained in:
parent
26eec3af74
commit
e163ac7185
@ -43,6 +43,7 @@ class MachineDominatorTree;
|
|||||||
class MachineLoopInfo;
|
class MachineLoopInfo;
|
||||||
class RegisterClassInfo;
|
class RegisterClassInfo;
|
||||||
class ScheduleDAGInstrs;
|
class ScheduleDAGInstrs;
|
||||||
|
class SchedDFSResult;
|
||||||
|
|
||||||
/// MachineSchedContext provides enough context from the MachineScheduler pass
|
/// MachineSchedContext provides enough context from the MachineScheduler pass
|
||||||
/// for the target to instantiate a scheduler.
|
/// for the target to instantiate a scheduler.
|
||||||
@ -119,6 +120,9 @@ public:
|
|||||||
/// be scheduled at the bottom.
|
/// be scheduled at the bottom.
|
||||||
virtual SUnit *pickNode(bool &IsTopNode) = 0;
|
virtual SUnit *pickNode(bool &IsTopNode) = 0;
|
||||||
|
|
||||||
|
/// \brief Scheduler callback to notify that a new subtree is scheduled.
|
||||||
|
virtual void scheduleTree(unsigned SubtreeID) {}
|
||||||
|
|
||||||
/// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
|
/// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
|
||||||
/// instruction and updated scheduled/remaining flags in the DAG nodes.
|
/// instruction and updated scheduled/remaining flags in the DAG nodes.
|
||||||
virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
|
virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
|
||||||
@ -164,6 +168,8 @@ public:
|
|||||||
|
|
||||||
iterator end() { return Queue.end(); }
|
iterator end() { return Queue.end(); }
|
||||||
|
|
||||||
|
ArrayRef<SUnit*> elements() { return Queue; }
|
||||||
|
|
||||||
iterator find(SUnit *SU) {
|
iterator find(SUnit *SU) {
|
||||||
return std::find(Queue.begin(), Queue.end(), SU);
|
return std::find(Queue.begin(), Queue.end(), SU);
|
||||||
}
|
}
|
||||||
@ -202,6 +208,11 @@ protected:
|
|||||||
RegisterClassInfo *RegClassInfo;
|
RegisterClassInfo *RegClassInfo;
|
||||||
MachineSchedStrategy *SchedImpl;
|
MachineSchedStrategy *SchedImpl;
|
||||||
|
|
||||||
|
/// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees
|
||||||
|
/// will be empty.
|
||||||
|
SchedDFSResult *DFSResult;
|
||||||
|
BitVector ScheduledTrees;
|
||||||
|
|
||||||
/// Topo - A topological ordering for SUnits which permits fast IsReachable
|
/// Topo - A topological ordering for SUnits which permits fast IsReachable
|
||||||
/// and similar queries.
|
/// and similar queries.
|
||||||
ScheduleDAGTopologicalSort Topo;
|
ScheduleDAGTopologicalSort Topo;
|
||||||
@ -243,7 +254,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S):
|
ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S):
|
||||||
ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
|
ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
|
||||||
AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S),
|
AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0),
|
||||||
Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(),
|
Topo(SUnits, &ExitSU), RPTracker(RegPressure), CurrentTop(),
|
||||||
TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure),
|
TopRPTracker(TopPressure), CurrentBottom(), BotRPTracker(BotPressure),
|
||||||
NextClusterPred(NULL), NextClusterSucc(NULL) {
|
NextClusterPred(NULL), NextClusterSucc(NULL) {
|
||||||
@ -252,10 +263,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ScheduleDAGMI() {
|
virtual ~ScheduleDAGMI();
|
||||||
DeleteContainerPointers(Mutations);
|
|
||||||
delete SchedImpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a postprocessing step to the DAG builder.
|
/// Add a postprocessing step to the DAG builder.
|
||||||
/// Mutations are applied in the order that they are added after normal DAG
|
/// Mutations are applied in the order that they are added after normal DAG
|
||||||
@ -308,6 +316,18 @@ public:
|
|||||||
|
|
||||||
const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
|
const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
|
||||||
|
|
||||||
|
/// Initialize a DFSResult after DAG building is complete, and before any
|
||||||
|
/// queue comparisons.
|
||||||
|
void initDFSResult();
|
||||||
|
|
||||||
|
/// 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.
|
||||||
|
const SchedDFSResult *getDFSResult() const { return DFSResult; }
|
||||||
|
|
||||||
|
BitVector &getScheduledTrees() { return ScheduledTrees; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Top-Level entry points for the schedule() driver...
|
// Top-Level entry points for the schedule() driver...
|
||||||
|
|
||||||
|
@ -56,6 +56,9 @@ static cl::opt<bool> EnableLoadCluster("misched-cluster", cl::Hidden,
|
|||||||
static cl::opt<bool> EnableMacroFusion("misched-fusion", cl::Hidden,
|
static cl::opt<bool> EnableMacroFusion("misched-fusion", cl::Hidden,
|
||||||
cl::desc("Enable scheduling for macro fusion."), cl::init(true));
|
cl::desc("Enable scheduling for macro fusion."), cl::init(true));
|
||||||
|
|
||||||
|
// DAG subtrees must have at least this many nodes.
|
||||||
|
static const unsigned MinSubtreeSize = 8;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Machine Instruction Scheduling Pass and Registry
|
// Machine Instruction Scheduling Pass and Registry
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -301,6 +304,12 @@ void ReadyQueue::dump() {
|
|||||||
// preservation.
|
// preservation.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
ScheduleDAGMI::~ScheduleDAGMI() {
|
||||||
|
delete DFSResult;
|
||||||
|
DeleteContainerPointers(Mutations);
|
||||||
|
delete SchedImpl;
|
||||||
|
}
|
||||||
|
|
||||||
bool ScheduleDAGMI::addEdge(SUnit *SuccSU, const SDep &PredDep) {
|
bool ScheduleDAGMI::addEdge(SUnit *SuccSU, const SDep &PredDep) {
|
||||||
if (SuccSU != &ExitSU) {
|
if (SuccSU != &ExitSU) {
|
||||||
// Do not use WillCreateCycle, it assumes SD scheduling.
|
// Do not use WillCreateCycle, it assumes SD scheduling.
|
||||||
@ -504,8 +513,6 @@ void ScheduleDAGMI::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));
|
||||||
|
|
||||||
if (ViewMISchedDAGs) viewGraph();
|
|
||||||
|
|
||||||
initQueues();
|
initQueues();
|
||||||
|
|
||||||
bool IsTopNode = false;
|
bool IsTopNode = false;
|
||||||
@ -554,6 +561,19 @@ void ScheduleDAGMI::postprocessDAG() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScheduleDAGMI::initDFSResult() {
|
||||||
|
if (!DFSResult)
|
||||||
|
DFSResult = new SchedDFSResult(/*BottomU*/true, MinSubtreeSize);
|
||||||
|
DFSResult->clear();
|
||||||
|
DFSResult->resize(SUnits.size());
|
||||||
|
ScheduledTrees.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScheduleDAGMI::computeDFSResult(ArrayRef<SUnit*> Roots) {
|
||||||
|
DFSResult->compute(Roots);
|
||||||
|
ScheduledTrees.resize(DFSResult->getNumSubtrees());
|
||||||
|
}
|
||||||
|
|
||||||
// Release all DAG roots for scheduling.
|
// Release all DAG roots for scheduling.
|
||||||
//
|
//
|
||||||
// Nodes with unreleased weak edges can still be roots.
|
// Nodes with unreleased weak edges can still be roots.
|
||||||
@ -655,6 +675,15 @@ void ScheduleDAGMI::updateQueues(SUnit *SU, bool IsTopNode) {
|
|||||||
|
|
||||||
SU->isScheduled = true;
|
SU->isScheduled = true;
|
||||||
|
|
||||||
|
if (DFSResult) {
|
||||||
|
unsigned SubtreeID = DFSResult->getSubtreeID(SU);
|
||||||
|
if (!ScheduledTrees.test(SubtreeID)) {
|
||||||
|
ScheduledTrees.set(SubtreeID);
|
||||||
|
DFSResult->scheduleTree(SubtreeID);
|
||||||
|
SchedImpl->scheduleTree(SubtreeID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Notify the scheduling strategy after updating the DAG.
|
// Notify the scheduling strategy after updating the DAG.
|
||||||
SchedImpl->schedNode(SU, IsTopNode);
|
SchedImpl->schedNode(SU, IsTopNode);
|
||||||
}
|
}
|
||||||
@ -1187,6 +1216,8 @@ 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();
|
||||||
|
|
||||||
// Initialize resource counts.
|
// Initialize resource counts.
|
||||||
|
|
||||||
// Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
|
// Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
|
||||||
@ -1247,6 +1278,8 @@ 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.
|
||||||
@ -2056,12 +2089,11 @@ ConvergingSchedRegistry("converge", "Standard converging scheduler.",
|
|||||||
namespace {
|
namespace {
|
||||||
/// \brief Order nodes by the ILP metric.
|
/// \brief Order nodes by the ILP metric.
|
||||||
struct ILPOrder {
|
struct ILPOrder {
|
||||||
SchedDFSResult *DFSResult;
|
const SchedDFSResult *DFSResult;
|
||||||
BitVector *ScheduledTrees;
|
const BitVector *ScheduledTrees;
|
||||||
bool MaximizeILP;
|
bool MaximizeILP;
|
||||||
|
|
||||||
ILPOrder(SchedDFSResult *dfs, BitVector *schedtrees, bool MaxILP)
|
ILPOrder(bool MaxILP): DFSResult(0), ScheduledTrees(0), MaximizeILP(MaxILP) {}
|
||||||
: DFSResult(dfs), ScheduledTrees(schedtrees), MaximizeILP(MaxILP) {}
|
|
||||||
|
|
||||||
/// \brief Apply a less-than relation on node priority.
|
/// \brief Apply a less-than relation on node priority.
|
||||||
///
|
///
|
||||||
@ -2099,26 +2131,23 @@ class ILPScheduler : public MachineSchedStrategy {
|
|||||||
/// (a motivating test case must be found).
|
/// (a motivating test case must be found).
|
||||||
static const unsigned SubtreeLimit = 16;
|
static const unsigned SubtreeLimit = 16;
|
||||||
|
|
||||||
SchedDFSResult DFSResult;
|
ScheduleDAGMI *DAG;
|
||||||
BitVector ScheduledTrees;
|
|
||||||
ILPOrder Cmp;
|
ILPOrder Cmp;
|
||||||
|
|
||||||
std::vector<SUnit*> ReadyQ;
|
std::vector<SUnit*> ReadyQ;
|
||||||
public:
|
public:
|
||||||
ILPScheduler(bool MaximizeILP)
|
ILPScheduler(bool MaximizeILP): DAG(0), Cmp(MaximizeILP) {}
|
||||||
: DFSResult(/*BottomUp=*/true, SubtreeLimit),
|
|
||||||
Cmp(&DFSResult, &ScheduledTrees, MaximizeILP) {}
|
|
||||||
|
|
||||||
virtual void initialize(ScheduleDAGMI *DAG) {
|
virtual void initialize(ScheduleDAGMI *dag) {
|
||||||
|
DAG = dag;
|
||||||
|
DAG->initDFSResult();
|
||||||
|
Cmp.DFSResult = DAG->getDFSResult();
|
||||||
|
Cmp.ScheduledTrees = &DAG->getScheduledTrees();
|
||||||
ReadyQ.clear();
|
ReadyQ.clear();
|
||||||
DFSResult.clear();
|
|
||||||
DFSResult.resize(DAG->SUnits.size());
|
|
||||||
ScheduledTrees.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void registerRoots() {
|
virtual void registerRoots() {
|
||||||
DFSResult.compute(ReadyQ);
|
DAG->computeDFSResult(ReadyQ);
|
||||||
ScheduledTrees.resize(DFSResult.getNumSubtrees());
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
@ -2135,21 +2164,22 @@ public:
|
|||||||
IsTopNode = false;
|
IsTopNode = false;
|
||||||
DEBUG(dbgs() << "*** Scheduling " << "SU(" << SU->NodeNum << "): "
|
DEBUG(dbgs() << "*** Scheduling " << "SU(" << SU->NodeNum << "): "
|
||||||
<< *SU->getInstr()
|
<< *SU->getInstr()
|
||||||
<< " ILP: " << DFSResult.getILP(SU)
|
<< " ILP: " << DAG->getDFSResult()->getILP(SU)
|
||||||
<< " Tree: " << DFSResult.getSubtreeID(SU) << " @"
|
<< " Tree: " << DAG->getDFSResult()->getSubtreeID(SU) << " @"
|
||||||
<< DFSResult.getSubtreeLevel(DFSResult.getSubtreeID(SU))<< '\n');
|
<< DAG->getDFSResult()->getSubtreeLevel(
|
||||||
|
DAG->getDFSResult()->getSubtreeID(SU)) << '\n');
|
||||||
return SU;
|
return SU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Scheduler callback to notify that a new subtree is scheduled.
|
||||||
|
virtual void scheduleTree(unsigned SubtreeID) {
|
||||||
|
std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
|
||||||
|
}
|
||||||
|
|
||||||
/// Callback after a node is scheduled. Mark a newly scheduled tree, notify
|
/// Callback after a node is scheduled. Mark a newly scheduled tree, notify
|
||||||
/// DFSResults, and resort the priority Q.
|
/// DFSResults, and resort the priority Q.
|
||||||
virtual void schedNode(SUnit *SU, bool IsTopNode) {
|
virtual void schedNode(SUnit *SU, bool IsTopNode) {
|
||||||
assert(!IsTopNode && "SchedDFSResult needs bottom-up");
|
assert(!IsTopNode && "SchedDFSResult needs bottom-up");
|
||||||
if (!ScheduledTrees.test(DFSResult.getSubtreeID(SU))) {
|
|
||||||
ScheduledTrees.set(DFSResult.getSubtreeID(SU));
|
|
||||||
DFSResult.scheduleTree(DFSResult.getSubtreeID(SU));
|
|
||||||
std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void releaseTopNode(SUnit *) { /*only called for top roots*/ }
|
virtual void releaseTopNode(SUnit *) { /*only called for top roots*/ }
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
; 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…
x
Reference in New Issue
Block a user