Fix 12513: Loop unrolling breaks with indirect branches.
[oota-llvm.git] / lib / CodeGen / MachineScheduler.cpp
index 10a318c46dcc91bfde28bebaaa2e708c50cc76d6..1d3241b8cc6b2d5361f20e203f2adf2bfb5848f5 100644 (file)
@@ -39,6 +39,9 @@ static cl::opt<bool> ForceBottomUp("misched-bottomup", cl::Hidden,
 #ifndef NDEBUG
 static cl::opt<bool> ViewMISchedDAGs("view-misched-dags", cl::Hidden,
   cl::desc("Pop up a window to show MISched dags after they are processed"));
+
+static cl::opt<unsigned> MISchedCutoff("misched-cutoff", cl::Hidden,
+  cl::desc("Stop scheduling after N instructions"), cl::init(~0U));
 #else
 static bool ViewMISchedDAGs = false;
 #endif // NDEBUG
@@ -224,6 +227,8 @@ bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) {
     assert(RemainingCount == 0 && "Instruction count mismatch!");
     Scheduler->finishBlock();
   }
+  Scheduler->finalizeSchedule();
+  DEBUG(LIS->print(dbgs()));
   return true;
 }
 
@@ -281,10 +286,15 @@ class ScheduleDAGMI : public ScheduleDAGInstrs {
 
   /// The bottom of the unscheduled zone.
   MachineBasicBlock::iterator CurrentBottom;
+
+  /// The number of instructions scheduled so far. Used to cut off the
+  /// scheduler at the point determined by misched-cutoff.
+  unsigned NumInstrsScheduled;
 public:
   ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S):
     ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS),
-    AA(C->AA), SchedImpl(S), CurrentTop(), CurrentBottom() {}
+    AA(C->AA), SchedImpl(S), CurrentTop(), CurrentBottom(),
+    NumInstrsScheduled(0) {}
 
   ~ScheduleDAGMI() {
     delete SchedImpl;
@@ -298,6 +308,7 @@ public:
 
 protected:
   void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
+  bool checkSchedLimit();
 
   void releaseSucc(SUnit *SU, SDep *SuccEdge);
   void releaseSuccessors(SUnit *SU);
@@ -360,12 +371,27 @@ void ScheduleDAGMI::releasePredecessors(SUnit *SU) {
 
 void ScheduleDAGMI::moveInstruction(MachineInstr *MI,
                                     MachineBasicBlock::iterator InsertPos) {
+  // Fix RegionBegin if the first instruction moves down.
+  if (&*RegionBegin == MI)
+    RegionBegin = llvm::next(RegionBegin);
   BB->splice(InsertPos, BB, MI);
   LIS->handleMove(MI);
+  // Fix RegionBegin if another instruction moves above the first instruction.
   if (RegionBegin == InsertPos)
     RegionBegin = MI;
 }
 
+bool ScheduleDAGMI::checkSchedLimit() {
+#ifndef NDEBUG
+  if (NumInstrsScheduled == MISchedCutoff && MISchedCutoff != ~0U) {
+    CurrentTop = CurrentBottom;
+    return false;
+  }
+  ++NumInstrsScheduled;
+#endif
+  return true;
+}
+
 /// schedule - Called back from MachineScheduler::runOnMachineFunction
 /// after setting up the current scheduling region.
 void ScheduleDAGMI::schedule() {
@@ -400,6 +426,8 @@ void ScheduleDAGMI::schedule() {
   while (SUnit *SU = SchedImpl->pickNode(IsTopNode)) {
     DEBUG(dbgs() << "*** " << (IsTopNode ? "Top" : "Bottom")
           << " Scheduling Instruction:\n"; SU->dump(this));
+    if (!checkSchedLimit())
+      break;
 
     // Move the instruction to its new location in the instruction stream.
     MachineInstr *MI = SU->getInstr();
@@ -418,6 +446,8 @@ void ScheduleDAGMI::schedule() {
       if (&*llvm::prior(CurrentBottom) == MI)
         --CurrentBottom;
       else {
+        if (&*CurrentTop == MI)
+          CurrentTop = llvm::next(CurrentTop);
         moveInstruction(MI, CurrentBottom);
         CurrentBottom = MI;
       }