fix an overly conservative caching issue that caused memdep to
[oota-llvm.git] / lib / CodeGen / RegAllocLinearScan.cpp
index 79bde1611f93e3a66837b7b69682a0672d23c3cb..9e97d89c62e129ac31b6061b698737ce5f9927ad 100644 (file)
@@ -16,6 +16,7 @@
 #include "VirtRegRewriter.h"
 #include "Spiller.h"
 #include "llvm/Function.h"
+#include "llvm/CodeGen/CalcSpillWeights.h"
 #include "llvm/CodeGen/LiveIntervalAnalysis.h"
 #include "llvm/CodeGen/LiveStackAnalysis.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
@@ -59,6 +60,11 @@ PreSplitIntervals("pre-alloc-split",
                   cl::desc("Pre-register allocation live interval splitting"),
                   cl::init(false), cl::Hidden);
 
+static cl::opt<bool>
+TrivCoalesceEnds("trivial-coalesce-ends",
+                  cl::desc("Attempt trivial coalescing of interval ends"),
+                  cl::init(false), cl::Hidden);
+
 static RegisterRegAlloc
 linearscanRegAlloc("linearscan", "linear scan register allocator",
                    createLinearScanRegisterAllocator);
@@ -182,6 +188,7 @@ namespace {
       // Make sure PassManager knows which analyses to make available
       // to coalescing and which analyses coalescing invalidates.
       AU.addRequiredTransitive<RegisterCoalescer>();
+      AU.addRequired<CalculateSpillWeights>();
       if (PreSplitIntervals)
         AU.addRequiredID(PreAllocSplittingID);
       AU.addRequired<LiveStacks>();
@@ -402,11 +409,17 @@ unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
   if ((Preference && Preference == Reg) || !cur.containsOneValue())
     return Reg;
 
-  VNInfo *vni = cur.begin()->valno;
+  // We cannot handle complicated live ranges. Simple linear stuff only.
+  if (cur.ranges.size() != 1)
+    return Reg;
+
+  const LiveRange &range = cur.ranges.front();
+
+  VNInfo *vni = range.valno;
   if (vni->isUnused())
     return Reg;
+
   unsigned CandReg;
-  bool forward;                 // extending physreg forward
   {
     MachineInstr *CopyMI;
     unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
@@ -414,14 +427,14 @@ unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
         (CopyMI = li_->getInstructionFromIndex(vni->def)) &&
         tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg))
       // Defined by a copy, try to extend SrcReg forward
-      CandReg = SrcReg, forward = true;
-    else if (cur.ranges.size()==1 &&
+      CandReg = SrcReg;
+    else if (TrivCoalesceEnds &&
              (CopyMI =
-              li_->getInstructionFromIndex(cur.begin()->end.getBaseIndex())) &&
+              li_->getInstructionFromIndex(range.end.getBaseIndex())) &&
              tii_->isMoveInstr(*CopyMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
              cur.reg == SrcReg)
       // Only used by a copy, try to extend DstReg backwards
-      CandReg = DstReg, forward = false;
+      CandReg = DstReg;
     else
       return Reg;
   }
@@ -438,13 +451,8 @@ unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
   if (!RC->contains(CandReg))
     return Reg;
 
-  if (forward) {
-    if (li_->conflictsWithPhysRegDef(cur, *vrm_, CandReg))
-      return Reg;
-  } else {
-    if (li_->conflictsWithPhysRegUse(cur, *vrm_, CandReg))
-      return Reg;
-  }
+  if (li_->conflictsWithPhysReg(cur, *vrm_, CandReg))
+    return Reg;
 
   // Try to coalesce.
   DEBUG(errs() << "Coalescing: " << cur << " -> " << tri_->getName(CandReg)
@@ -883,7 +891,7 @@ namespace {
     const RALinScan &Allocator;
 
   public:
-    WeightCompare(const RALinScan &Alloc) : Allocator(Alloc) {};
+    WeightCompare(const RALinScan &Alloc) : Allocator(Alloc) {}
 
     typedef std::pair<unsigned, float> RegWeightPair;
     bool operator()(const RegWeightPair &LHS, const RegWeightPair &RHS) const {
@@ -1265,9 +1273,9 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) {
 
   // The earliest start of a Spilled interval indicates up to where
   // in handled we need to roll back
+  assert(!spillIs.empty() && "No spill intervals?"); 
+  SlotIndex earliestStart = spillIs[0]->beginIndex();
   
-  LiveInterval *earliestStartInterval = cur;
-
   // Spill live intervals of virtual regs mapped to the physical register we
   // want to clear (and its aliases).  We only spill those that overlap with the
   // current interval as the rest do not affect its allocation. we also keep
@@ -1278,19 +1286,16 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) {
     LiveInterval *sli = spillIs.back();
     spillIs.pop_back();
     DEBUG(errs() << "\t\t\tspilling(a): " << *sli << '\n');
-    earliestStartInterval =
-      (earliestStartInterval->beginIndex() < sli->beginIndex()) ?
-         earliestStartInterval : sli;
+    if (sli->beginIndex() < earliestStart)
+      earliestStart = sli->beginIndex();
        
     std::vector<LiveInterval*> newIs;
-    newIs = spiller_->spill(sli, spillIs);
+    newIs = spiller_->spill(sli, spillIs, &earliestStart);
     addStackInterval(sli, ls_, li_, mri_, *vrm_);
     std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
     spilled.insert(sli->reg);
   }
 
-  SlotIndex earliestStart = earliestStartInterval->beginIndex();
-
   DEBUG(errs() << "\t\trolling back to: " << earliestStart << '\n');
 
   // Scan handled in reverse order up to the earliest start of a
@@ -1299,7 +1304,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) {
   while (!handled_.empty()) {
     LiveInterval* i = handled_.back();
     // If this interval starts before t we are done.
-    if (i->beginIndex() < earliestStart)
+    if (!i->empty() && i->beginIndex() < earliestStart)
       break;
     DEBUG(errs() << "\t\t\tundo changes for: " << *i << '\n');
     handled_.pop_back();