mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-19 17:33:29 +00:00
Reorganize ListScheduleBottomUp in preparation for modeling machine cycles and instruction issue.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122491 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3d420cb2fe
commit
2902736a50
@ -83,6 +83,9 @@ private:
|
|||||||
/// AvailableQueue - The priority queue to use for the available SUnits.
|
/// AvailableQueue - The priority queue to use for the available SUnits.
|
||||||
SchedulingPriorityQueue *AvailableQueue;
|
SchedulingPriorityQueue *AvailableQueue;
|
||||||
|
|
||||||
|
/// CurCycle - The current scheduler state corresponds to this cycle.
|
||||||
|
unsigned CurCycle;
|
||||||
|
|
||||||
/// LiveRegDefs - A set of physical registers and their definition
|
/// LiveRegDefs - A set of physical registers and their definition
|
||||||
/// that are "live". These nodes must be scheduled before any other nodes that
|
/// that are "live". These nodes must be scheduled before any other nodes that
|
||||||
/// modifies the registers can be scheduled.
|
/// modifies the registers can be scheduled.
|
||||||
@ -99,7 +102,7 @@ public:
|
|||||||
bool isbottomup, bool needlatency,
|
bool isbottomup, bool needlatency,
|
||||||
SchedulingPriorityQueue *availqueue)
|
SchedulingPriorityQueue *availqueue)
|
||||||
: ScheduleDAGSDNodes(mf), isBottomUp(isbottomup), NeedLatency(needlatency),
|
: ScheduleDAGSDNodes(mf), isBottomUp(isbottomup), NeedLatency(needlatency),
|
||||||
AvailableQueue(availqueue), Topo(SUnits) {
|
AvailableQueue(availqueue), CurCycle(0), Topo(SUnits) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~ScheduleDAGRRList() {
|
~ScheduleDAGRRList() {
|
||||||
@ -141,19 +144,21 @@ private:
|
|||||||
void ReleaseSucc(SUnit *SU, const SDep *SuccEdge);
|
void ReleaseSucc(SUnit *SU, const SDep *SuccEdge);
|
||||||
void ReleaseSuccessors(SUnit *SU);
|
void ReleaseSuccessors(SUnit *SU);
|
||||||
void CapturePred(SDep *PredEdge);
|
void CapturePred(SDep *PredEdge);
|
||||||
void ScheduleNodeBottomUp(SUnit*, unsigned);
|
void ScheduleNodeBottomUp(SUnit*);
|
||||||
void ScheduleNodeTopDown(SUnit*, unsigned);
|
|
||||||
void UnscheduleNodeBottomUp(SUnit*);
|
void UnscheduleNodeBottomUp(SUnit*);
|
||||||
void BacktrackBottomUp(SUnit*, unsigned, unsigned&);
|
void BacktrackBottomUp(SUnit*, unsigned);
|
||||||
SUnit *CopyAndMoveSuccessors(SUnit*);
|
SUnit *CopyAndMoveSuccessors(SUnit*);
|
||||||
void InsertCopiesAndMoveSuccs(SUnit*, unsigned,
|
void InsertCopiesAndMoveSuccs(SUnit*, unsigned,
|
||||||
const TargetRegisterClass*,
|
const TargetRegisterClass*,
|
||||||
const TargetRegisterClass*,
|
const TargetRegisterClass*,
|
||||||
SmallVector<SUnit*, 2>&);
|
SmallVector<SUnit*, 2>&);
|
||||||
bool DelayForLiveRegsBottomUp(SUnit*, SmallVector<unsigned, 4>&);
|
bool DelayForLiveRegsBottomUp(SUnit*, SmallVector<unsigned, 4>&);
|
||||||
void ListScheduleTopDown();
|
SUnit *PickNodeToScheduleBottomUp();
|
||||||
void ListScheduleBottomUp();
|
void ListScheduleBottomUp();
|
||||||
|
|
||||||
|
void ScheduleNodeTopDown(SUnit*);
|
||||||
|
void ListScheduleTopDown();
|
||||||
|
|
||||||
|
|
||||||
/// CreateNewSUnit - Creates a new SUnit and returns a pointer to it.
|
/// CreateNewSUnit - Creates a new SUnit and returns a pointer to it.
|
||||||
/// Updates the topological ordering if required.
|
/// Updates the topological ordering if required.
|
||||||
@ -192,6 +197,7 @@ void ScheduleDAGRRList::Schedule() {
|
|||||||
<< "********** List Scheduling BB#" << BB->getNumber()
|
<< "********** List Scheduling BB#" << BB->getNumber()
|
||||||
<< " '" << BB->getName() << "' **********\n");
|
<< " '" << BB->getName() << "' **********\n");
|
||||||
|
|
||||||
|
CurCycle = 0;
|
||||||
NumLiveRegs = 0;
|
NumLiveRegs = 0;
|
||||||
LiveRegDefs.resize(TRI->getNumRegs(), NULL);
|
LiveRegDefs.resize(TRI->getNumRegs(), NULL);
|
||||||
LiveRegGens.resize(TRI->getNumRegs(), NULL);
|
LiveRegGens.resize(TRI->getNumRegs(), NULL);
|
||||||
@ -289,7 +295,7 @@ void ScheduleDAGRRList::ReleasePredecessors(SUnit *SU) {
|
|||||||
/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending
|
/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending
|
||||||
/// count of its predecessors. If a predecessor pending count is zero, add it to
|
/// count of its predecessors. If a predecessor pending count is zero, add it to
|
||||||
/// the Available queue.
|
/// the Available queue.
|
||||||
void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU, unsigned CurCycle) {
|
void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) {
|
||||||
DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: ");
|
DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: ");
|
||||||
DEBUG(SU->dump(this));
|
DEBUG(SU->dump(this));
|
||||||
|
|
||||||
@ -381,8 +387,7 @@ void ScheduleDAGRRList::UnscheduleNodeBottomUp(SUnit *SU) {
|
|||||||
|
|
||||||
/// BacktrackBottomUp - Backtrack scheduling to a previous cycle specified in
|
/// BacktrackBottomUp - Backtrack scheduling to a previous cycle specified in
|
||||||
/// BTCycle in order to schedule a specific node.
|
/// BTCycle in order to schedule a specific node.
|
||||||
void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, unsigned BtCycle,
|
void ScheduleDAGRRList::BacktrackBottomUp(SUnit *SU, unsigned BtCycle) {
|
||||||
unsigned &CurCycle) {
|
|
||||||
SUnit *OldSU = NULL;
|
SUnit *OldSU = NULL;
|
||||||
while (CurCycle > BtCycle) {
|
while (CurCycle > BtCycle) {
|
||||||
OldSU = Sequence.back();
|
OldSU = Sequence.back();
|
||||||
@ -734,50 +739,40 @@ DelayForLiveRegsBottomUp(SUnit *SU, SmallVector<unsigned, 4> &LRegs) {
|
|||||||
return !LRegs.empty();
|
return !LRegs.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a node that can be scheduled in this cycle. Requirements:
|
||||||
/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up
|
/// (1) Ready: latency has been satisfied
|
||||||
/// schedulers.
|
/// (2) No Hazards: resources are available (TBD)
|
||||||
void ScheduleDAGRRList::ListScheduleBottomUp() {
|
/// (3) No Interferences: may unschedule to break register interferences.
|
||||||
unsigned CurCycle = 0;
|
SUnit *ScheduleDAGRRList::PickNodeToScheduleBottomUp() {
|
||||||
|
SmallVector<SUnit*, 4> Interferences;
|
||||||
// Release any predecessors of the special Exit node.
|
|
||||||
ReleasePredecessors(&ExitSU);
|
|
||||||
|
|
||||||
// Add root to Available queue.
|
|
||||||
if (!SUnits.empty()) {
|
|
||||||
SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
|
|
||||||
assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!");
|
|
||||||
RootSU->isAvailable = true;
|
|
||||||
AvailableQueue->push(RootSU);
|
|
||||||
}
|
|
||||||
|
|
||||||
// While Available queue is not empty, grab the node with the highest
|
|
||||||
// priority. If it is not ready put it back. Schedule the node.
|
|
||||||
SmallVector<SUnit*, 4> NotReady;
|
|
||||||
DenseMap<SUnit*, SmallVector<unsigned, 4> > LRegsMap;
|
DenseMap<SUnit*, SmallVector<unsigned, 4> > LRegsMap;
|
||||||
Sequence.reserve(SUnits.size());
|
|
||||||
while (!AvailableQueue->empty()) {
|
|
||||||
bool Delayed = false;
|
|
||||||
LRegsMap.clear();
|
|
||||||
SUnit *CurSU = AvailableQueue->pop();
|
SUnit *CurSU = AvailableQueue->pop();
|
||||||
while (CurSU) {
|
while (CurSU) {
|
||||||
SmallVector<unsigned, 4> LRegs;
|
SmallVector<unsigned, 4> LRegs;
|
||||||
if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
|
if (!DelayForLiveRegsBottomUp(CurSU, LRegs))
|
||||||
break;
|
break;
|
||||||
Delayed = true;
|
|
||||||
LRegsMap.insert(std::make_pair(CurSU, LRegs));
|
LRegsMap.insert(std::make_pair(CurSU, LRegs));
|
||||||
|
|
||||||
CurSU->isPending = true; // This SU is not in AvailableQueue right now.
|
CurSU->isPending = true; // This SU is not in AvailableQueue right now.
|
||||||
NotReady.push_back(CurSU);
|
Interferences.push_back(CurSU);
|
||||||
CurSU = AvailableQueue->pop();
|
CurSU = AvailableQueue->pop();
|
||||||
}
|
}
|
||||||
|
if (CurSU) {
|
||||||
|
// Add the nodes that aren't ready back onto the available list.
|
||||||
|
for (unsigned i = 0, e = Interferences.size(); i != e; ++i) {
|
||||||
|
Interferences[i]->isPending = false;
|
||||||
|
assert(Interferences[i]->isAvailable && "must still be available");
|
||||||
|
AvailableQueue->push(Interferences[i]);
|
||||||
|
}
|
||||||
|
return CurSU;
|
||||||
|
}
|
||||||
|
|
||||||
// All candidates are delayed due to live physical reg dependencies.
|
// All candidates are delayed due to live physical reg dependencies.
|
||||||
// Try backtracking, code duplication, or inserting cross class copies
|
// Try backtracking, code duplication, or inserting cross class copies
|
||||||
// to resolve it.
|
// to resolve it.
|
||||||
if (Delayed && !CurSU) {
|
for (unsigned i = 0, e = Interferences.size(); i != e; ++i) {
|
||||||
for (unsigned i = 0, e = NotReady.size(); i != e; ++i) {
|
SUnit *TrySU = Interferences[i];
|
||||||
SUnit *TrySU = NotReady[i];
|
|
||||||
SmallVector<unsigned, 4> &LRegs = LRegsMap[TrySU];
|
SmallVector<unsigned, 4> &LRegs = LRegsMap[TrySU];
|
||||||
|
|
||||||
// Try unscheduling up to the point where it's safe to schedule
|
// Try unscheduling up to the point where it's safe to schedule
|
||||||
@ -790,25 +785,29 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
|
|||||||
}
|
}
|
||||||
SUnit *OldSU = Sequence[LiveCycle];
|
SUnit *OldSU = Sequence[LiveCycle];
|
||||||
if (!WillCreateCycle(TrySU, OldSU)) {
|
if (!WillCreateCycle(TrySU, OldSU)) {
|
||||||
BacktrackBottomUp(TrySU, LiveCycle, CurCycle);
|
BacktrackBottomUp(TrySU, LiveCycle);
|
||||||
|
|
||||||
// Force the current node to be scheduled before the node that
|
// Force the current node to be scheduled before the node that
|
||||||
// requires the physical reg dep.
|
// requires the physical reg dep.
|
||||||
if (OldSU->isAvailable) {
|
if (OldSU->isAvailable) {
|
||||||
OldSU->isAvailable = false;
|
OldSU->isAvailable = false;
|
||||||
|
if (!OldSU->isPending)
|
||||||
AvailableQueue->remove(OldSU);
|
AvailableQueue->remove(OldSU);
|
||||||
}
|
}
|
||||||
AddPred(TrySU, SDep(OldSU, SDep::Order, /*Latency=*/1,
|
AddPred(TrySU, SDep(OldSU, SDep::Order, /*Latency=*/1,
|
||||||
/*Reg=*/0, /*isNormalMemory=*/false,
|
/*Reg=*/0, /*isNormalMemory=*/false,
|
||||||
/*isMustAlias=*/false, /*isArtificial=*/true));
|
/*isMustAlias=*/false, /*isArtificial=*/true));
|
||||||
|
|
||||||
// If one or more successors has been unscheduled, then the current
|
// If one or more successors has been unscheduled, then the current
|
||||||
// node is no longer avaialable. Schedule a successor that's now
|
// node is no longer avaialable. Schedule a successor that's now
|
||||||
// available instead.
|
// available instead.
|
||||||
if (!TrySU->isAvailable)
|
if (!TrySU->isAvailable) {
|
||||||
CurSU = AvailableQueue->pop();
|
CurSU = AvailableQueue->pop();
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
CurSU = TrySU;
|
CurSU = TrySU;
|
||||||
TrySU->isPending = false;
|
TrySU->isPending = false;
|
||||||
NotReady.erase(NotReady.begin()+i);
|
Interferences.erase(Interferences.begin()+i);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -820,7 +819,7 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
|
|||||||
// values to break the dependency. In case even that doesn't work,
|
// values to break the dependency. In case even that doesn't work,
|
||||||
// insert cross class copies.
|
// insert cross class copies.
|
||||||
// If it's not too expensive, i.e. cost != -1, issue copies.
|
// If it's not too expensive, i.e. cost != -1, issue copies.
|
||||||
SUnit *TrySU = NotReady[0];
|
SUnit *TrySU = Interferences[0];
|
||||||
SmallVector<unsigned, 4> &LRegs = LRegsMap[TrySU];
|
SmallVector<unsigned, 4> &LRegs = LRegsMap[TrySU];
|
||||||
assert(LRegs.size() == 1 && "Can't handle this yet!");
|
assert(LRegs.size() == 1 && "Can't handle this yet!");
|
||||||
unsigned Reg = LRegs[0];
|
unsigned Reg = LRegs[0];
|
||||||
@ -862,19 +861,43 @@ void ScheduleDAGRRList::ListScheduleBottomUp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert(CurSU && "Unable to resolve live physical register dependencies!");
|
assert(CurSU && "Unable to resolve live physical register dependencies!");
|
||||||
}
|
|
||||||
|
|
||||||
// Add the nodes that aren't ready back onto the available list.
|
// Add the nodes that aren't ready back onto the available list.
|
||||||
for (unsigned i = 0, e = NotReady.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Interferences.size(); i != e; ++i) {
|
||||||
NotReady[i]->isPending = false;
|
Interferences[i]->isPending = false;
|
||||||
// May no longer be available due to backtracking.
|
// May no longer be available due to backtracking.
|
||||||
if (NotReady[i]->isAvailable)
|
if (Interferences[i]->isAvailable) {
|
||||||
AvailableQueue->push(NotReady[i]);
|
AvailableQueue->push(Interferences[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CurSU;
|
||||||
}
|
}
|
||||||
NotReady.clear();
|
|
||||||
|
|
||||||
if (CurSU)
|
/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up
|
||||||
ScheduleNodeBottomUp(CurSU, CurCycle);
|
/// schedulers.
|
||||||
|
void ScheduleDAGRRList::ListScheduleBottomUp() {
|
||||||
|
// Release any predecessors of the special Exit node.
|
||||||
|
ReleasePredecessors(&ExitSU);
|
||||||
|
|
||||||
|
// Add root to Available queue.
|
||||||
|
if (!SUnits.empty()) {
|
||||||
|
SUnit *RootSU = &SUnits[DAG->getRoot().getNode()->getNodeId()];
|
||||||
|
assert(RootSU->Succs.empty() && "Graph root shouldn't have successors!");
|
||||||
|
RootSU->isAvailable = true;
|
||||||
|
AvailableQueue->push(RootSU);
|
||||||
|
}
|
||||||
|
|
||||||
|
// While Available queue is not empty, grab the node with the highest
|
||||||
|
// priority. If it is not ready put it back. Schedule the node.
|
||||||
|
Sequence.reserve(SUnits.size());
|
||||||
|
while (!AvailableQueue->empty()) {
|
||||||
|
// Pick the best node to schedule taking all constraints into
|
||||||
|
// consideration.
|
||||||
|
SUnit *SU = PickNodeToScheduleBottomUp();
|
||||||
|
|
||||||
|
if (SU)
|
||||||
|
ScheduleNodeBottomUp(SU);
|
||||||
|
|
||||||
++CurCycle;
|
++CurCycle;
|
||||||
AvailableQueue->setCurCycle(CurCycle);
|
AvailableQueue->setCurCycle(CurCycle);
|
||||||
}
|
}
|
||||||
@ -928,7 +951,7 @@ void ScheduleDAGRRList::ReleaseSuccessors(SUnit *SU) {
|
|||||||
/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
|
/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
|
||||||
/// count of its successors. If a successor pending count is zero, add it to
|
/// count of its successors. If a successor pending count is zero, add it to
|
||||||
/// the Available queue.
|
/// the Available queue.
|
||||||
void ScheduleDAGRRList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
|
void ScheduleDAGRRList::ScheduleNodeTopDown(SUnit *SU) {
|
||||||
DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
|
DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
|
||||||
DEBUG(SU->dump(this));
|
DEBUG(SU->dump(this));
|
||||||
|
|
||||||
@ -966,7 +989,7 @@ void ScheduleDAGRRList::ListScheduleTopDown() {
|
|||||||
SUnit *CurSU = AvailableQueue->pop();
|
SUnit *CurSU = AvailableQueue->pop();
|
||||||
|
|
||||||
if (CurSU)
|
if (CurSU)
|
||||||
ScheduleNodeTopDown(CurSU, CurCycle);
|
ScheduleNodeTopDown(CurSU);
|
||||||
++CurCycle;
|
++CurCycle;
|
||||||
AvailableQueue->setCurCycle(CurCycle);
|
AvailableQueue->setCurCycle(CurCycle);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user