Instead of adding dependence edges between terminator instructions
and every other instruction in their blocks to keep the terminator
instructions at the end, teach the post-RA scheduler how to operate
on ranges of instructions, and exclude terminators from the range
of instructions that get scheduled.

Also, exclude mid-block labels, such as EH_LABEL instructions, and
schedule code before them separately from code after them. This
fixes problems with the post-RA scheduler moving code past
EH_LABELs.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62366 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp
index 7b5690c..0ffdd05 100644
--- a/lib/CodeGen/ScheduleDAGInstrs.cpp
+++ b/lib/CodeGen/ScheduleDAGInstrs.cpp
@@ -112,10 +112,16 @@
   std::map<const Value *, SUnit *> MemDefs;
   std::map<const Value *, std::vector<SUnit *> > MemUses;
 
-  // Terminators can perform control transfers, we we need to make sure that
-  // all the work of the block is done before the terminator.
+  // If we have an SUnit which is representing a terminator instruction, we
+  // can use it as a place-holder successor for inter-block dependencies.
   SUnit *Terminator = 0;
 
+  // Terminators can perform control transfers, we we need to make sure that
+  // all the work of the block is done before the terminator. Labels can
+  // mark points of interest for various types of meta-data (eg. EH data),
+  // and we need to make sure nothing is scheduled around them.
+  SUnit *SchedulingBarrier = 0;
+
   LoopDependencies LoopRegs(MLI, MDT);
 
   // Track which regs are live into a loop, to help guide back-edge-aware
@@ -137,7 +143,7 @@
   unsigned SpecialAddressLatency =
     TM.getSubtarget<TargetSubtarget>().getSpecialAddressLatency();
 
-  for (MachineBasicBlock::iterator MII = BB->end(), MIE = BB->begin();
+  for (MachineBasicBlock::iterator MII = End, MIE = Begin;
        MII != MIE; --MII) {
     MachineInstr *MI = prior(MII);
     const TargetInstrDesc &TID = MI->getDesc();
@@ -368,11 +374,26 @@
       }
     }
 
-    // Add chain edges from the terminator to ensure that all the work of the
-    // block is completed before any control transfers.
-    if (Terminator && SU->Succs.empty())
-      Terminator->addPred(SDep(SU, SDep::Order, SU->Latency));
+    // Add chain edges from terminators and labels to ensure that no
+    // instructions are scheduled past them.
+    if (SchedulingBarrier && SU->Succs.empty())
+      SchedulingBarrier->addPred(SDep(SU, SDep::Order, SU->Latency));
+    // If we encounter a mid-block label, we need to go back and add
+    // dependencies on SUnits we've already processed to prevent the
+    // label from moving downward.
+    if (MI->isLabel())
+      for (SUnit *I = SU; I != &SUnits[0]; --I) {
+        SUnit *SuccSU = SU-1;
+        SuccSU->addPred(SDep(SU, SDep::Order, SU->Latency));
+        MachineInstr *SuccMI = SuccSU->getInstr();
+        if (SuccMI->getDesc().isTerminator() || SuccMI->isLabel())
+          break;
+      }
+    // If this instruction obstructs all scheduling, remember it.
     if (TID.isTerminator() || MI->isLabel())
+      SchedulingBarrier = SU;
+    // If this instruction is a terminator, remember it.
+    if (TID.isTerminator())
       Terminator = SU;
   }
 
@@ -413,8 +434,11 @@
 MachineBasicBlock *ScheduleDAGInstrs::EmitSchedule() {
   // For MachineInstr-based scheduling, we're rescheduling the instructions in
   // the block, so start by removing them from the block.
-  while (!BB->empty())
-    BB->remove(BB->begin());
+  while (Begin != End) {
+    MachineBasicBlock::iterator I = Begin;
+    ++Begin;
+    BB->remove(I);
+  }
 
   // Then re-insert them according to the given schedule.
   for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
@@ -425,7 +449,7 @@
       continue;
     }
 
-    BB->push_back(SU->getInstr());
+    BB->insert(End, SU->getInstr());
   }
 
   return BB;