Add basic hazard recognizer support. noop insertion isn't complete yet though.
llvm-svn: 26558
This commit is contained in:
parent
ef9aa1294a
commit
e50c092b7c
|
|
@ -160,6 +160,52 @@ struct ls_rr_sort : public std::binary_function<SUnit*, SUnit*, bool> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// 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.
|
/// ScheduleDAGList - List scheduler.
|
||||||
class ScheduleDAGList : public ScheduleDAG {
|
class ScheduleDAGList : public ScheduleDAG {
|
||||||
private:
|
private:
|
||||||
|
|
@ -176,14 +222,21 @@ private:
|
||||||
/// it is top-down.
|
/// it is top-down.
|
||||||
bool isBottomUp;
|
bool isBottomUp;
|
||||||
|
|
||||||
|
/// HazardRec - The hazard recognizer to use.
|
||||||
|
HazardRecognizer *HazardRec;
|
||||||
|
|
||||||
typedef std::priority_queue<SUnit*, std::vector<SUnit*>, ls_rr_sort>
|
typedef std::priority_queue<SUnit*, std::vector<SUnit*>, ls_rr_sort>
|
||||||
AvailableQueueTy;
|
AvailableQueueTy;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ScheduleDAGList(SelectionDAG &dag, MachineBasicBlock *bb,
|
ScheduleDAGList(SelectionDAG &dag, MachineBasicBlock *bb,
|
||||||
const TargetMachine &tm, bool isbottomup)
|
const TargetMachine &tm, bool isbottomup,
|
||||||
|
HazardRecognizer *HR = 0)
|
||||||
: ScheduleDAG(listSchedulingBURR, dag, bb, tm),
|
: 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() {
|
~ScheduleDAGList() {
|
||||||
SUnit *SU = HeadSUnit;
|
SUnit *SU = HeadSUnit;
|
||||||
|
|
@ -192,6 +245,8 @@ public:
|
||||||
delete SU;
|
delete SU;
|
||||||
SU = NextSU;
|
SU = NextSU;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete HazardRec;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule();
|
void Schedule();
|
||||||
|
|
@ -411,6 +466,7 @@ void ScheduleDAGList::ListScheduleTopDown() {
|
||||||
// Emit the entry node first.
|
// Emit the entry node first.
|
||||||
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
|
SUnit *Entry = SUnitMap[DAG.getEntryNode().Val];
|
||||||
ScheduleNodeTopDown(Available, Entry);
|
ScheduleNodeTopDown(Available, Entry);
|
||||||
|
HazardRec->EmitInstruction(Entry->Node);
|
||||||
|
|
||||||
// All leaves to Available queue.
|
// All leaves to Available queue.
|
||||||
for (SUnit *SU = HeadSUnit; SU != NULL; SU = SU->Next) {
|
for (SUnit *SU = HeadSUnit; SU != NULL; SU = SU->Next) {
|
||||||
|
|
@ -423,23 +479,46 @@ void ScheduleDAGList::ListScheduleTopDown() {
|
||||||
// priority. If it is not ready put it back. Schedule the node.
|
// priority. If it is not ready put it back. Schedule the node.
|
||||||
std::vector<SUnit*> NotReady;
|
std::vector<SUnit*> NotReady;
|
||||||
while (!Available.empty()) {
|
while (!Available.empty()) {
|
||||||
|
SUnit *FoundNode = 0;
|
||||||
|
|
||||||
|
bool HasNoopHazards = false;
|
||||||
|
do {
|
||||||
SUnit *CurrNode = Available.top();
|
SUnit *CurrNode = Available.top();
|
||||||
Available.pop();
|
Available.pop();
|
||||||
|
HazardRecognizer::HazardType HT =
|
||||||
// FIXME: when priorities make sense, reenable this.
|
HazardRec->getHazardType(CurrNode->Node);
|
||||||
while (0 && !isReady(CurrNode, CurrCycle)) {
|
if (HT == HazardRecognizer::NoHazard) {
|
||||||
NotReady.push_back(CurrNode);
|
FoundNode = CurrNode;
|
||||||
CurrNode = Available.top();
|
break;
|
||||||
Available.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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.
|
// Add the nodes that aren't ready back onto the available list.
|
||||||
while (!NotReady.empty()) {
|
while (!NotReady.empty()) {
|
||||||
Available.push(NotReady.back());
|
Available.push(NotReady.back());
|
||||||
NotReady.pop_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
|
#ifndef NDEBUG
|
||||||
|
|
@ -651,10 +730,20 @@ llvm::ScheduleDAG* llvm::createBURRListDAGScheduler(SelectionDAG &DAG,
|
||||||
return new ScheduleDAGList(DAG, BB, DAG.getTarget(), true);
|
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
|
/// createTDG5ListDAGScheduler - This creates a top-down list scheduler for
|
||||||
/// the PowerPC G5. FIXME: pull the priority function out into the PPC
|
/// the PowerPC G5. FIXME: pull the priority function out into the PPC
|
||||||
/// backend!
|
/// backend!
|
||||||
ScheduleDAG* llvm::createTDG5ListDAGScheduler(SelectionDAG &DAG,
|
ScheduleDAG* llvm::createTDG5ListDAGScheduler(SelectionDAG &DAG,
|
||||||
MachineBasicBlock *BB) {
|
MachineBasicBlock *BB) {
|
||||||
return new ScheduleDAGList(DAG, BB, DAG.getTarget(), false);
|
return new ScheduleDAGList(DAG, BB, DAG.getTarget(), false,
|
||||||
|
new G5HazardRecognizer());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue