mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-17 21:35:07 +00:00
Move some methods around so that BU specific code is together, TD specific code
is together, and direction independent code is together. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26712 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
309cf8a713
commit
7d82b00048
@ -217,252 +217,9 @@ SUnit *ScheduleDAGList::NewSUnit(SDNode *N) {
|
|||||||
return &SUnits.back();
|
return &SUnits.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to
|
/// BuildSchedUnits - Build SUnits from the selection dag that we are input.
|
||||||
/// the Available queue is the count reaches zero. Also update its cycle bound.
|
/// This SUnit graph is similar to the SelectionDAG, but represents flagged
|
||||||
void ScheduleDAGList::ReleasePred(SUnit *PredSU, bool isChain) {
|
/// together nodes with a single SUnit.
|
||||||
// FIXME: the distance between two nodes is not always == the predecessor's
|
|
||||||
// latency. For example, the reader can very well read the register written
|
|
||||||
// by the predecessor later than the issue cycle. It also depends on the
|
|
||||||
// interrupt model (drain vs. freeze).
|
|
||||||
PredSU->CycleBound = std::max(PredSU->CycleBound,CurrCycle + PredSU->Latency);
|
|
||||||
|
|
||||||
if (!isChain)
|
|
||||||
PredSU->NumSuccsLeft--;
|
|
||||||
else
|
|
||||||
PredSU->NumChainSuccsLeft--;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (PredSU->NumSuccsLeft < 0 || PredSU->NumChainSuccsLeft < 0) {
|
|
||||||
std::cerr << "*** List scheduling failed! ***\n";
|
|
||||||
PredSU->dump(&DAG);
|
|
||||||
std::cerr << " has been released too many times!\n";
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((PredSU->NumSuccsLeft + PredSU->NumChainSuccsLeft) == 0) {
|
|
||||||
// EntryToken has to go last! Special case it here.
|
|
||||||
if (PredSU->Node->getOpcode() != ISD::EntryToken) {
|
|
||||||
PredSU->isAvailable = true;
|
|
||||||
PriorityQueue->push(PredSU);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
|
|
||||||
/// the Available queue is the count reaches zero. Also update its cycle bound.
|
|
||||||
void ScheduleDAGList::ReleaseSucc(SUnit *SuccSU, bool isChain) {
|
|
||||||
// FIXME: the distance between two nodes is not always == the predecessor's
|
|
||||||
// latency. For example, the reader can very well read the register written
|
|
||||||
// by the predecessor later than the issue cycle. It also depends on the
|
|
||||||
// interrupt model (drain vs. freeze).
|
|
||||||
SuccSU->CycleBound = std::max(SuccSU->CycleBound,CurrCycle + SuccSU->Latency);
|
|
||||||
|
|
||||||
if (!isChain)
|
|
||||||
SuccSU->NumPredsLeft--;
|
|
||||||
else
|
|
||||||
SuccSU->NumChainPredsLeft--;
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
if (SuccSU->NumPredsLeft < 0 || SuccSU->NumChainPredsLeft < 0) {
|
|
||||||
std::cerr << "*** List scheduling failed! ***\n";
|
|
||||||
SuccSU->dump(&DAG);
|
|
||||||
std::cerr << " has been released too many times!\n";
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((SuccSU->NumPredsLeft + SuccSU->NumChainPredsLeft) == 0) {
|
|
||||||
SuccSU->isAvailable = true;
|
|
||||||
PriorityQueue->push(SuccSU);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending
|
|
||||||
/// count of its predecessors. If a predecessor pending count is zero, add it to
|
|
||||||
/// the Available queue.
|
|
||||||
void ScheduleDAGList::ScheduleNodeBottomUp(SUnit *SU) {
|
|
||||||
DEBUG(std::cerr << "*** Scheduling: ");
|
|
||||||
DEBUG(SU->dump(&DAG));
|
|
||||||
|
|
||||||
Sequence.push_back(SU);
|
|
||||||
|
|
||||||
// Bottom up: release predecessors
|
|
||||||
for (std::set<std::pair<SUnit*, bool> >::iterator I = SU->Preds.begin(),
|
|
||||||
E = SU->Preds.end(); I != E; ++I) {
|
|
||||||
ReleasePred(I->first, I->second);
|
|
||||||
if (!I->second)
|
|
||||||
SU->NumPredsLeft--;
|
|
||||||
}
|
|
||||||
CurrCycle++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
|
|
||||||
/// count of its successors. If a successor pending count is zero, add it to
|
|
||||||
/// the Available queue.
|
|
||||||
void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU) {
|
|
||||||
DEBUG(std::cerr << "*** Scheduling: ");
|
|
||||||
DEBUG(SU->dump(&DAG));
|
|
||||||
|
|
||||||
Sequence.push_back(SU);
|
|
||||||
|
|
||||||
// Bottom up: release successors.
|
|
||||||
for (std::set<std::pair<SUnit*, bool> >::iterator I = SU->Succs.begin(),
|
|
||||||
E = SU->Succs.end(); I != E; ++I) {
|
|
||||||
ReleaseSucc(I->first, I->second);
|
|
||||||
if (!I->second)
|
|
||||||
SU->NumSuccsLeft--;
|
|
||||||
}
|
|
||||||
CurrCycle++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// isReady - True if node's lower cycle bound is less or equal to the current
|
|
||||||
/// scheduling cycle. Always true if all nodes have uniform latency 1.
|
|
||||||
static inline bool isReady(SUnit *SU, unsigned CurrCycle) {
|
|
||||||
return SU->CycleBound <= CurrCycle;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up
|
|
||||||
/// schedulers.
|
|
||||||
void ScheduleDAGList::ListScheduleBottomUp() {
|
|
||||||
// Add root to Available queue.
|
|
||||||
PriorityQueue->push(SUnitMap[DAG.getRoot().Val]);
|
|
||||||
|
|
||||||
// While Available queue is not empty, grab the node with the highest
|
|
||||||
// priority. If it is not ready put it back. Schedule the node.
|
|
||||||
std::vector<SUnit*> NotReady;
|
|
||||||
while (!PriorityQueue->empty()) {
|
|
||||||
SUnit *CurrNode = PriorityQueue->pop();
|
|
||||||
|
|
||||||
while (!isReady(CurrNode, CurrCycle)) {
|
|
||||||
NotReady.push_back(CurrNode);
|
|
||||||
CurrNode = PriorityQueue->pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the nodes that aren't ready back onto the available list.
|
|
||||||
PriorityQueue->push_all(NotReady);
|
|
||||||
NotReady.clear();
|
|
||||||
|
|
||||||
ScheduleNodeBottomUp(CurrNode);
|
|
||||||
CurrNode->isScheduled = true;
|
|
||||||
PriorityQueue->ScheduledNode(CurrNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add entry node last
|
|
||||||
if (DAG.getEntryNode().Val != DAG.getRoot().Val) {
|
|
||||||
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
|
|
||||||
Sequence.push_back(Entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse the order if it is bottom up.
|
|
||||||
std::reverse(Sequence.begin(), Sequence.end());
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// Verify that all SUnits were scheduled.
|
|
||||||
bool AnyNotSched = false;
|
|
||||||
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
|
||||||
if (SUnits[i].NumSuccsLeft != 0 || SUnits[i].NumChainSuccsLeft != 0) {
|
|
||||||
if (!AnyNotSched)
|
|
||||||
std::cerr << "*** List scheduling failed! ***\n";
|
|
||||||
SUnits[i].dump(&DAG);
|
|
||||||
std::cerr << "has not been scheduled!\n";
|
|
||||||
AnyNotSched = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(!AnyNotSched);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ListScheduleTopDown - The main loop of list scheduling for top-down
|
|
||||||
/// schedulers.
|
|
||||||
void ScheduleDAGList::ListScheduleTopDown() {
|
|
||||||
// Emit the entry node first.
|
|
||||||
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
|
|
||||||
ScheduleNodeTopDown(Entry);
|
|
||||||
HazardRec->EmitInstruction(Entry->Node);
|
|
||||||
|
|
||||||
// All leaves to Available queue.
|
|
||||||
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
|
||||||
// It is available if it has no predecessors.
|
|
||||||
if (SUnits[i].Preds.size() == 0 && &SUnits[i] != Entry)
|
|
||||||
PriorityQueue->push(&SUnits[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// While Available queue is not empty, grab the node with the highest
|
|
||||||
// priority. If it is not ready put it back. Schedule the node.
|
|
||||||
std::vector<SUnit*> NotReady;
|
|
||||||
while (!PriorityQueue->empty()) {
|
|
||||||
SUnit *FoundNode = 0;
|
|
||||||
|
|
||||||
bool HasNoopHazards = false;
|
|
||||||
do {
|
|
||||||
SUnit *CurNode = PriorityQueue->pop();
|
|
||||||
|
|
||||||
// Get the node represented by this SUnit.
|
|
||||||
SDNode *N = CurNode->Node;
|
|
||||||
// If this is a pseudo op, like copyfromreg, look to see if there is a
|
|
||||||
// real target node flagged to it. If so, use the target node.
|
|
||||||
for (unsigned i = 0, e = CurNode->FlaggedNodes.size();
|
|
||||||
N->getOpcode() < ISD::BUILTIN_OP_END && i != e; ++i)
|
|
||||||
N = CurNode->FlaggedNodes[i];
|
|
||||||
|
|
||||||
HazardRecognizer::HazardType HT = HazardRec->getHazardType(N);
|
|
||||||
if (HT == HazardRecognizer::NoHazard) {
|
|
||||||
FoundNode = CurNode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember if this is a noop hazard.
|
|
||||||
HasNoopHazards |= HT == HazardRecognizer::NoopHazard;
|
|
||||||
|
|
||||||
NotReady.push_back(CurNode);
|
|
||||||
} while (!PriorityQueue->empty());
|
|
||||||
|
|
||||||
// Add the nodes that aren't ready back onto the available list.
|
|
||||||
PriorityQueue->push_all(NotReady);
|
|
||||||
NotReady.clear();
|
|
||||||
|
|
||||||
// If we found a node to schedule, do it now.
|
|
||||||
if (FoundNode) {
|
|
||||||
ScheduleNodeTopDown(FoundNode);
|
|
||||||
HazardRec->EmitInstruction(FoundNode->Node);
|
|
||||||
FoundNode->isScheduled = true;
|
|
||||||
PriorityQueue->ScheduledNode(FoundNode);
|
|
||||||
} else if (!HasNoopHazards) {
|
|
||||||
// Otherwise, we have a pipeline stall, but no other problem, just advance
|
|
||||||
// the current cycle and try again.
|
|
||||||
DEBUG(std::cerr << "*** Advancing cycle, no work to do\n");
|
|
||||||
HazardRec->AdvanceCycle();
|
|
||||||
++NumStalls;
|
|
||||||
} else {
|
|
||||||
// Otherwise, we have no instructions to issue and we have instructions
|
|
||||||
// that will fault if we don't do this right. This is the case for
|
|
||||||
// processors without pipeline interlocks and other cases.
|
|
||||||
DEBUG(std::cerr << "*** Emitting noop\n");
|
|
||||||
HazardRec->EmitNoop();
|
|
||||||
Sequence.push_back(0); // NULL SUnit* -> noop
|
|
||||||
++NumNoops;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// Verify that all SUnits were scheduled.
|
|
||||||
bool AnyNotSched = false;
|
|
||||||
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
|
||||||
if (SUnits[i].NumPredsLeft != 0 || SUnits[i].NumChainPredsLeft != 0) {
|
|
||||||
if (!AnyNotSched)
|
|
||||||
std::cerr << "*** List scheduling failed! ***\n";
|
|
||||||
SUnits[i].dump(&DAG);
|
|
||||||
std::cerr << "has not been scheduled!\n";
|
|
||||||
AnyNotSched = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(!AnyNotSched);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ScheduleDAGList::BuildSchedUnits() {
|
void ScheduleDAGList::BuildSchedUnits() {
|
||||||
// Reserve entries in the vector for each of the SUnits we are creating. This
|
// Reserve entries in the vector for each of the SUnits we are creating. This
|
||||||
// ensure that reallocation of the vector won't happen, so SUnit*'s won't get
|
// ensure that reallocation of the vector won't happen, so SUnit*'s won't get
|
||||||
@ -649,6 +406,258 @@ void ScheduleDAGList::Schedule() {
|
|||||||
EmitSchedule();
|
EmitSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Bottom-Up Scheduling
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. Add it to
|
||||||
|
/// the Available queue is the count reaches zero. Also update its cycle bound.
|
||||||
|
void ScheduleDAGList::ReleasePred(SUnit *PredSU, bool isChain) {
|
||||||
|
// FIXME: the distance between two nodes is not always == the predecessor's
|
||||||
|
// latency. For example, the reader can very well read the register written
|
||||||
|
// by the predecessor later than the issue cycle. It also depends on the
|
||||||
|
// interrupt model (drain vs. freeze).
|
||||||
|
PredSU->CycleBound = std::max(PredSU->CycleBound,CurrCycle + PredSU->Latency);
|
||||||
|
|
||||||
|
if (!isChain)
|
||||||
|
PredSU->NumSuccsLeft--;
|
||||||
|
else
|
||||||
|
PredSU->NumChainSuccsLeft--;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (PredSU->NumSuccsLeft < 0 || PredSU->NumChainSuccsLeft < 0) {
|
||||||
|
std::cerr << "*** List scheduling failed! ***\n";
|
||||||
|
PredSU->dump(&DAG);
|
||||||
|
std::cerr << " has been released too many times!\n";
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((PredSU->NumSuccsLeft + PredSU->NumChainSuccsLeft) == 0) {
|
||||||
|
// EntryToken has to go last! Special case it here.
|
||||||
|
if (PredSU->Node->getOpcode() != ISD::EntryToken) {
|
||||||
|
PredSU->isAvailable = true;
|
||||||
|
PriorityQueue->push(PredSU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending
|
||||||
|
/// count of its predecessors. If a predecessor pending count is zero, add it to
|
||||||
|
/// the Available queue.
|
||||||
|
void ScheduleDAGList::ScheduleNodeBottomUp(SUnit *SU) {
|
||||||
|
DEBUG(std::cerr << "*** Scheduling: ");
|
||||||
|
DEBUG(SU->dump(&DAG));
|
||||||
|
|
||||||
|
Sequence.push_back(SU);
|
||||||
|
|
||||||
|
// Bottom up: release predecessors
|
||||||
|
for (std::set<std::pair<SUnit*, bool> >::iterator I = SU->Preds.begin(),
|
||||||
|
E = SU->Preds.end(); I != E; ++I) {
|
||||||
|
ReleasePred(I->first, I->second);
|
||||||
|
if (!I->second)
|
||||||
|
SU->NumPredsLeft--;
|
||||||
|
}
|
||||||
|
CurrCycle++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isReady - True if node's lower cycle bound is less or equal to the current
|
||||||
|
/// scheduling cycle. Always true if all nodes have uniform latency 1.
|
||||||
|
static inline bool isReady(SUnit *SU, unsigned CurrCycle) {
|
||||||
|
return SU->CycleBound <= CurrCycle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ListScheduleBottomUp - The main loop of list scheduling for bottom-up
|
||||||
|
/// schedulers.
|
||||||
|
void ScheduleDAGList::ListScheduleBottomUp() {
|
||||||
|
// Add root to Available queue.
|
||||||
|
PriorityQueue->push(SUnitMap[DAG.getRoot().Val]);
|
||||||
|
|
||||||
|
// While Available queue is not empty, grab the node with the highest
|
||||||
|
// priority. If it is not ready put it back. Schedule the node.
|
||||||
|
std::vector<SUnit*> NotReady;
|
||||||
|
while (!PriorityQueue->empty()) {
|
||||||
|
SUnit *CurrNode = PriorityQueue->pop();
|
||||||
|
|
||||||
|
while (!isReady(CurrNode, CurrCycle)) {
|
||||||
|
NotReady.push_back(CurrNode);
|
||||||
|
CurrNode = PriorityQueue->pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the nodes that aren't ready back onto the available list.
|
||||||
|
PriorityQueue->push_all(NotReady);
|
||||||
|
NotReady.clear();
|
||||||
|
|
||||||
|
ScheduleNodeBottomUp(CurrNode);
|
||||||
|
CurrNode->isScheduled = true;
|
||||||
|
PriorityQueue->ScheduledNode(CurrNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add entry node last
|
||||||
|
if (DAG.getEntryNode().Val != DAG.getRoot().Val) {
|
||||||
|
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
|
||||||
|
Sequence.push_back(Entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse the order if it is bottom up.
|
||||||
|
std::reverse(Sequence.begin(), Sequence.end());
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that all SUnits were scheduled.
|
||||||
|
bool AnyNotSched = false;
|
||||||
|
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
||||||
|
if (SUnits[i].NumSuccsLeft != 0 || SUnits[i].NumChainSuccsLeft != 0) {
|
||||||
|
if (!AnyNotSched)
|
||||||
|
std::cerr << "*** List scheduling failed! ***\n";
|
||||||
|
SUnits[i].dump(&DAG);
|
||||||
|
std::cerr << "has not been scheduled!\n";
|
||||||
|
AnyNotSched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(!AnyNotSched);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Top-Down Scheduling
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. Add it to
|
||||||
|
/// the Available queue is the count reaches zero. Also update its cycle bound.
|
||||||
|
void ScheduleDAGList::ReleaseSucc(SUnit *SuccSU, bool isChain) {
|
||||||
|
// FIXME: the distance between two nodes is not always == the predecessor's
|
||||||
|
// latency. For example, the reader can very well read the register written
|
||||||
|
// by the predecessor later than the issue cycle. It also depends on the
|
||||||
|
// interrupt model (drain vs. freeze).
|
||||||
|
SuccSU->CycleBound = std::max(SuccSU->CycleBound,CurrCycle + SuccSU->Latency);
|
||||||
|
|
||||||
|
if (!isChain)
|
||||||
|
SuccSU->NumPredsLeft--;
|
||||||
|
else
|
||||||
|
SuccSU->NumChainPredsLeft--;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
if (SuccSU->NumPredsLeft < 0 || SuccSU->NumChainPredsLeft < 0) {
|
||||||
|
std::cerr << "*** List scheduling failed! ***\n";
|
||||||
|
SuccSU->dump(&DAG);
|
||||||
|
std::cerr << " has been released too many times!\n";
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((SuccSU->NumPredsLeft + SuccSU->NumChainPredsLeft) == 0) {
|
||||||
|
SuccSU->isAvailable = true;
|
||||||
|
PriorityQueue->push(SuccSU);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ScheduleNodeTopDown - Add the node to the schedule. Decrement the pending
|
||||||
|
/// count of its successors. If a successor pending count is zero, add it to
|
||||||
|
/// the Available queue.
|
||||||
|
void ScheduleDAGList::ScheduleNodeTopDown(SUnit *SU) {
|
||||||
|
DEBUG(std::cerr << "*** Scheduling: ");
|
||||||
|
DEBUG(SU->dump(&DAG));
|
||||||
|
|
||||||
|
Sequence.push_back(SU);
|
||||||
|
|
||||||
|
// Bottom up: release successors.
|
||||||
|
for (std::set<std::pair<SUnit*, bool> >::iterator I = SU->Succs.begin(),
|
||||||
|
E = SU->Succs.end(); I != E; ++I) {
|
||||||
|
ReleaseSucc(I->first, I->second);
|
||||||
|
if (!I->second)
|
||||||
|
SU->NumSuccsLeft--;
|
||||||
|
}
|
||||||
|
CurrCycle++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ListScheduleTopDown - The main loop of list scheduling for top-down
|
||||||
|
/// schedulers.
|
||||||
|
void ScheduleDAGList::ListScheduleTopDown() {
|
||||||
|
// Emit the entry node first.
|
||||||
|
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
|
||||||
|
ScheduleNodeTopDown(Entry);
|
||||||
|
HazardRec->EmitInstruction(Entry->Node);
|
||||||
|
|
||||||
|
// All leaves to Available queue.
|
||||||
|
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
||||||
|
// It is available if it has no predecessors.
|
||||||
|
if (SUnits[i].Preds.size() == 0 && &SUnits[i] != Entry)
|
||||||
|
PriorityQueue->push(&SUnits[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// While Available queue is not empty, grab the node with the highest
|
||||||
|
// priority. If it is not ready put it back. Schedule the node.
|
||||||
|
std::vector<SUnit*> NotReady;
|
||||||
|
while (!PriorityQueue->empty()) {
|
||||||
|
SUnit *FoundNode = 0;
|
||||||
|
|
||||||
|
bool HasNoopHazards = false;
|
||||||
|
do {
|
||||||
|
SUnit *CurNode = PriorityQueue->pop();
|
||||||
|
|
||||||
|
// Get the node represented by this SUnit.
|
||||||
|
SDNode *N = CurNode->Node;
|
||||||
|
// If this is a pseudo op, like copyfromreg, look to see if there is a
|
||||||
|
// real target node flagged to it. If so, use the target node.
|
||||||
|
for (unsigned i = 0, e = CurNode->FlaggedNodes.size();
|
||||||
|
N->getOpcode() < ISD::BUILTIN_OP_END && i != e; ++i)
|
||||||
|
N = CurNode->FlaggedNodes[i];
|
||||||
|
|
||||||
|
HazardRecognizer::HazardType HT = HazardRec->getHazardType(N);
|
||||||
|
if (HT == HazardRecognizer::NoHazard) {
|
||||||
|
FoundNode = CurNode;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember if this is a noop hazard.
|
||||||
|
HasNoopHazards |= HT == HazardRecognizer::NoopHazard;
|
||||||
|
|
||||||
|
NotReady.push_back(CurNode);
|
||||||
|
} while (!PriorityQueue->empty());
|
||||||
|
|
||||||
|
// Add the nodes that aren't ready back onto the available list.
|
||||||
|
PriorityQueue->push_all(NotReady);
|
||||||
|
NotReady.clear();
|
||||||
|
|
||||||
|
// If we found a node to schedule, do it now.
|
||||||
|
if (FoundNode) {
|
||||||
|
ScheduleNodeTopDown(FoundNode);
|
||||||
|
HazardRec->EmitInstruction(FoundNode->Node);
|
||||||
|
FoundNode->isScheduled = true;
|
||||||
|
PriorityQueue->ScheduledNode(FoundNode);
|
||||||
|
} else if (!HasNoopHazards) {
|
||||||
|
// Otherwise, we have a pipeline stall, but no other problem, just advance
|
||||||
|
// the current cycle and try again.
|
||||||
|
DEBUG(std::cerr << "*** Advancing cycle, no work to do\n");
|
||||||
|
HazardRec->AdvanceCycle();
|
||||||
|
++NumStalls;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we have no instructions to issue and we have instructions
|
||||||
|
// that will fault if we don't do this right. This is the case for
|
||||||
|
// processors without pipeline interlocks and other cases.
|
||||||
|
DEBUG(std::cerr << "*** Emitting noop\n");
|
||||||
|
HazardRec->EmitNoop();
|
||||||
|
Sequence.push_back(0); // NULL SUnit* -> noop
|
||||||
|
++NumNoops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that all SUnits were scheduled.
|
||||||
|
bool AnyNotSched = false;
|
||||||
|
for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
|
||||||
|
if (SUnits[i].NumPredsLeft != 0 || SUnits[i].NumChainPredsLeft != 0) {
|
||||||
|
if (!AnyNotSched)
|
||||||
|
std::cerr << "*** List scheduling failed! ***\n";
|
||||||
|
SUnits[i].dump(&DAG);
|
||||||
|
std::cerr << "has not been scheduled!\n";
|
||||||
|
AnyNotSched = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(!AnyNotSched);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// RegReductionPriorityQueue Implementation
|
// RegReductionPriorityQueue Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user