summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2013-12-11 22:33:43 +0000
committerHal Finkel <hfinkel@anl.gov>2013-12-11 22:33:43 +0000
commit4fd3b1de2adee547f4b3055dcc5293a2934f8366 (patch)
tree0512085243d932020c975f53f5fcefe3230b2b61 /llvm/lib/CodeGen
parentc33843178d7cb63e213ad1be8c0c6e6906772668 (diff)
downloadbcm5719-llvm-4fd3b1de2adee547f4b3055dcc5293a2934f8366.tar.gz
bcm5719-llvm-4fd3b1de2adee547f4b3055dcc5293a2934f8366.zip
Add two additional hazard recognizer functions
This adds two additional functions to the hazard recognizer interface. These are optional (in the sense that the default implementations preserve the current behavior), and used by the post-RA scheduler. Upcoming commits will use this functionality in order to improve dispatch-group formation on the POWER7 and related cores. Dispatch groups are an odd construct: sometimes we need to insert nops to force a new one to start (for performance reasons), and some instructions need to appear in certain positions within a group, but the groups are not fundamentally cycle based (they can contain instructions with data dependencies with non-trivial latencies). Motivation: unsigned PreEmitNoops(SUnit *) - Used to force the post-RA scheduler to insert nops to force a new dispatch group to begin. We already have a NoopHazard, and this is also still needed. However, NoopHazard only causes a nop to be inserted if there are no other available instructions, and so is not always sufficient. The number of nops to insert depends on state that only the hazard recognizer has, so a general callback is necessary. bool ShouldPreferAnother(SUnit *) - Used to avoid scheduling instructions that would start a new dispatch group when others are available that could be part of the current dispatch group. In this case, we don't want to issue nops, because the non-preferred instruction will implicitly start a new dispatch group regardless. Although the motivation for these functions is driven by the PowerPC backend, they are completely general. llvm-svn: 197084
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/PostRASchedulerList.cpp50
1 files changed, 43 insertions, 7 deletions
diff --git a/llvm/lib/CodeGen/PostRASchedulerList.cpp b/llvm/lib/CodeGen/PostRASchedulerList.cpp
index 1afc1eca00a..d8afbbbbe7d 100644
--- a/llvm/lib/CodeGen/PostRASchedulerList.cpp
+++ b/llvm/lib/CodeGen/PostRASchedulerList.cpp
@@ -192,6 +192,7 @@ namespace {
bool ToggleKillFlag(MachineInstr *MI, MachineOperand &MO);
void dumpSchedule() const;
+ void emitNoop(unsigned CurCycle);
};
}
@@ -630,6 +631,14 @@ void SchedulePostRATDList::ScheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
AvailableQueue.scheduledNode(SU);
}
+/// emitNoop - Add a noop to the current instruction sequence.
+void SchedulePostRATDList::emitNoop(unsigned CurCycle) {
+ DEBUG(dbgs() << "*** Emitting noop in cycle " << CurCycle << '\n');
+ HazardRec->EmitNoop();
+ Sequence.push_back(0); // NULL here means noop
+ ++NumNoops;
+}
+
/// ListScheduleTopDown - The main loop of list scheduling for top-down
/// schedulers.
void SchedulePostRATDList::ListScheduleTopDown() {
@@ -678,7 +687,7 @@ void SchedulePostRATDList::ListScheduleTopDown() {
DEBUG(dbgs() << "\n*** Examining Available\n"; AvailableQueue.dump(this));
- SUnit *FoundSUnit = 0;
+ SUnit *FoundSUnit = 0, *NotPreferredSUnit = 0;
bool HasNoopHazards = false;
while (!AvailableQueue.empty()) {
SUnit *CurSUnit = AvailableQueue.pop();
@@ -686,8 +695,19 @@ void SchedulePostRATDList::ListScheduleTopDown() {
ScheduleHazardRecognizer::HazardType HT =
HazardRec->getHazardType(CurSUnit, 0/*no stalls*/);
if (HT == ScheduleHazardRecognizer::NoHazard) {
- FoundSUnit = CurSUnit;
- break;
+ if (HazardRec->ShouldPreferAnother(CurSUnit)) {
+ if (!NotPreferredSUnit) {
+ // If this is the first non-preferred node for this cycle, then
+ // record it and continue searching for a preferred node. If this
+ // is not the first non-preferred node, then treat it as though
+ // there had been a hazard.
+ NotPreferredSUnit = CurSUnit;
+ continue;
+ }
+ } else {
+ FoundSUnit = CurSUnit;
+ break;
+ }
}
// Remember if this is a noop hazard.
@@ -696,6 +716,20 @@ void SchedulePostRATDList::ListScheduleTopDown() {
NotReady.push_back(CurSUnit);
}
+ // If we have a non-preferred node, push it back onto the available list.
+ // If we did not find a preferred node, then schedule this first
+ // non-preferred node.
+ if (NotPreferredSUnit) {
+ if (!FoundSUnit) {
+ DEBUG(dbgs() << "*** Will schedule a non-preferred instruction...\n");
+ FoundSUnit = NotPreferredSUnit;
+ } else {
+ AvailableQueue.push(NotPreferredSUnit);
+ }
+
+ NotPreferredSUnit = 0;
+ }
+
// Add the nodes that aren't ready back onto the available list.
if (!NotReady.empty()) {
AvailableQueue.push_all(NotReady);
@@ -704,6 +738,11 @@ void SchedulePostRATDList::ListScheduleTopDown() {
// If we found a node to schedule...
if (FoundSUnit) {
+ // If we need to emit noops prior to this instruction, then do so.
+ unsigned NumPreNoops = HazardRec->PreEmitNoops(FoundSUnit);
+ for (unsigned i = 0; i != NumPreNoops; ++i)
+ emitNoop(CurCycle);
+
// ... schedule the node...
ScheduleNodeTopDown(FoundSUnit, CurCycle);
HazardRec->EmitInstruction(FoundSUnit);
@@ -728,10 +767,7 @@ void SchedulePostRATDList::ListScheduleTopDown() {
// 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(dbgs() << "*** Emitting noop in cycle " << CurCycle << '\n');
- HazardRec->EmitNoop();
- Sequence.push_back(0); // NULL here means noop
- ++NumNoops;
+ emitNoop(CurCycle);
}
++CurCycle;
OpenPOWER on IntegriCloud