[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sun Mar 5 14:45:13 PST 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
ScheduleDAGList.cpp updated: 1.11 -> 1.12
---
Log message:
Add basic hazard recognizer support. noop insertion isn't complete yet though.
---
Diffs of the changes: (+104 -15)
ScheduleDAGList.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 104 insertions(+), 15 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.11 llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.12
--- llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.11 Sun Mar 5 15:10:33 2006
+++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp Sun Mar 5 16:45:01 2006
@@ -160,6 +160,52 @@
}
};
+
+/// HazardRecognizer - This determines whether or not an instruction can be
+/// issued this cycle, and whether or not a noop needs to be inserted to handle
+/// the hazard.
+namespace {
+ class HazardRecognizer {
+ public:
+ virtual ~HazardRecognizer() {}
+
+ enum HazardType {
+ NoHazard, // This instruction can be emitted at this cycle.
+ Hazard, // This instruction can't be emitted at this cycle.
+ NoopHazard, // This instruction can't be emitted, and needs noops.
+ };
+
+ /// getHazardType - Return the hazard type of emitting this node. There are
+ /// three possible results. Either:
+ /// * NoHazard: it is legal to issue this instruction on this cycle.
+ /// * Hazard: issuing this instruction would stall the machine. If some
+ /// other instruction is available, issue it first.
+ /// * NoopHazard: issuing this instruction would break the program. If
+ /// some other instruction can be issued, do so, otherwise issue a noop.
+ virtual HazardType getHazardType(SDNode *Node) {
+ return NoHazard;
+ }
+
+ /// EmitInstruction - This callback is invoked when an instruction is
+ /// emitted, to advance the hazard state.
+ virtual void EmitInstruction(SDNode *Node) {
+ }
+
+ /// AdvanceCycle - This callback is invoked when no instructions can be
+ /// issued on this cycle without a hazard. This should increment the
+ /// internal state of the hazard recognizer so that previously "Hazard"
+ /// instructions will now not be hazards.
+ virtual void AdvanceCycle() {
+ }
+
+ /// EmitNoop - This callback is invoked when a noop was added to the
+ /// instruction stream.
+ virtual void EmitNoop() {
+ }
+ };
+}
+
+
/// ScheduleDAGList - List scheduler.
class ScheduleDAGList : public ScheduleDAG {
private:
@@ -176,14 +222,21 @@
/// it is top-down.
bool isBottomUp;
+ /// HazardRec - The hazard recognizer to use.
+ HazardRecognizer *HazardRec;
+
typedef std::priority_queue<SUnit*, std::vector<SUnit*>, ls_rr_sort>
AvailableQueueTy;
public:
ScheduleDAGList(SelectionDAG &dag, MachineBasicBlock *bb,
- const TargetMachine &tm, bool isbottomup)
+ const TargetMachine &tm, bool isbottomup,
+ HazardRecognizer *HR = 0)
: ScheduleDAG(listSchedulingBURR, dag, bb, tm),
- CurrCycle(0), HeadSUnit(NULL), TailSUnit(NULL), isBottomUp(isbottomup) {}
+ CurrCycle(0), HeadSUnit(NULL), TailSUnit(NULL), isBottomUp(isbottomup) {
+ if (HR == 0) HR = new HazardRecognizer();
+ HazardRec = HR;
+ }
~ScheduleDAGList() {
SUnit *SU = HeadSUnit;
@@ -192,6 +245,8 @@
delete SU;
SU = NextSU;
}
+
+ delete HazardRec;
}
void Schedule();
@@ -411,7 +466,8 @@
// Emit the entry node first.
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
ScheduleNodeTopDown(Available, Entry);
-
+ HazardRec->EmitInstruction(Entry->Node);
+
// All leaves to Available queue.
for (SUnit *SU = HeadSUnit; SU != NULL; SU = SU->Next) {
// It is available if it has no predecessors.
@@ -423,23 +479,46 @@
// priority. If it is not ready put it back. Schedule the node.
std::vector<SUnit*> NotReady;
while (!Available.empty()) {
- SUnit *CurrNode = Available.top();
- Available.pop();
-
- // FIXME: when priorities make sense, reenable this.
- while (0 && !isReady(CurrNode, CurrCycle)) {
- NotReady.push_back(CurrNode);
- CurrNode = Available.top();
- Available.pop();
- }
+ SUnit *FoundNode = 0;
+ bool HasNoopHazards = false;
+ do {
+ SUnit *CurrNode = Available.top();
+ Available.pop();
+ HazardRecognizer::HazardType HT =
+ HazardRec->getHazardType(CurrNode->Node);
+ if (HT == HazardRecognizer::NoHazard) {
+ FoundNode = CurrNode;
+ break;
+ }
+
+ // Remember if this is a noop hazard.
+ HasNoopHazards |= HT == HazardRecognizer::NoopHazard;
+
+ NotReady.push_back(CurrNode);
+ } while (!Available.empty());
+
// Add the nodes that aren't ready back onto the available list.
while (!NotReady.empty()) {
Available.push(NotReady.back());
NotReady.pop_back();
}
-
- ScheduleNodeTopDown(Available, CurrNode);
+
+ // If we found a node to schedule, do it now.
+ if (FoundNode) {
+ ScheduleNodeTopDown(Available, FoundNode);
+ HazardRec->EmitInstruction(FoundNode->Node);
+ } else if (!HasNoopHazards) {
+ // Otherwise, we have a pipeline stall, but no other problem, just advance
+ // the current cycle and try again.
+ HazardRec->AdvanceCycle();
+ } 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.
+ HazardRec->EmitNoop();
+ // FIXME: Add a noop to the schedule!!
+ }
}
#ifndef NDEBUG
@@ -651,10 +730,20 @@
return new ScheduleDAGList(DAG, BB, DAG.getTarget(), true);
}
+/// G5HazardRecognizer - A hazard recognizer for the PowerPC G5 processor.
+/// FIXME: Implement
+/// FIXME: Move to the PowerPC backend.
+class G5HazardRecognizer : public HazardRecognizer {
+public:
+ G5HazardRecognizer() {}
+};
+
+
/// createTDG5ListDAGScheduler - This creates a top-down list scheduler for
/// the PowerPC G5. FIXME: pull the priority function out into the PPC
/// backend!
ScheduleDAG* llvm::createTDG5ListDAGScheduler(SelectionDAG &DAG,
MachineBasicBlock *BB) {
- return new ScheduleDAGList(DAG, BB, DAG.getTarget(), false);
+ return new ScheduleDAGList(DAG, BB, DAG.getTarget(), false,
+ new G5HazardRecognizer());
}
More information about the llvm-commits
mailing list