Make load->store deletion a bit smarter. This allows us to compile this:
[oota-llvm.git] / lib / CodeGen / LiveInterval.cpp
index 53ffbe3fca457fa6b84ea7dc2744b56160446500..d4c572154be836785cb8af8455ac40446d37978b 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -19,6 +19,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/LiveInterval.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Streams.h"
 #include "llvm/Target/MRegisterInfo.h"
@@ -124,7 +125,7 @@ void LiveInterval::extendIntervalEndTo(Ranges::iterator I, unsigned NewEnd) {
   ranges.erase(next(I), MergeTo);
 
   // Update kill info.
-  removeKills(*ValNo, OldEnd, I->end-1);
+  removeKills(ValNo, OldEnd, I->end-1);
 
   // If the newly formed range now touches the range after it and if they have
   // the same value number, merge the two ranges into one range.
@@ -205,6 +206,9 @@ LiveInterval::addRangeFrom(LiveRange LR, iterator From) {
         // endpoint as well.
         if (End > it->end)
           extendIntervalEndTo(it, End);
+        else if (End < it->end)
+          // Overlapping intervals, there might have been a kill here.
+          removeKill(it->valno, End);
         return it;
       }
     } else {
@@ -233,7 +237,7 @@ void LiveInterval::removeRange(unsigned Start, unsigned End) {
   // If the span we are removing is at the start of the LiveRange, adjust it.
   if (I->start == Start) {
     if (I->end == End) {
-      removeKills(*I->valno, Start, End);
+      removeKills(I->valno, Start, End);
       ranges.erase(I);  // Removed the whole LiveRange.
     } else
       I->start = End;
@@ -243,7 +247,7 @@ void LiveInterval::removeRange(unsigned Start, unsigned End) {
   // Otherwise if the span we are removing is at the end of the LiveRange,
   // adjust the other way.
   if (I->end == End) {
-    removeKills(*I->valno, Start, End);
+    removeKills(I->valno, Start, End);
     I->end = Start;
     return;
   }
@@ -285,8 +289,8 @@ LiveInterval::FindLiveRangeContaining(unsigned Idx) {
 /// join - Join two live intervals (this, and other) together.  This applies
 /// mappings to the value numbers in the LHS/RHS intervals as specified.  If
 /// the intervals are not joinable, this aborts.
-void LiveInterval::join(LiveInterval &Other, int *LHSValNoAssignments,
-                        int *RHSValNoAssignments, 
+void LiveInterval::join(LiveInterval &Other, const int *LHSValNoAssignments,
+                        const int *RHSValNoAssignments, 
                         SmallVector<VNInfo*, 16> &NewVNInfo) {
   // Determine if any of our live range values are mapped.  This is uncommon, so
   // we want to avoid the interval scan if not. 
@@ -296,17 +300,8 @@ void LiveInterval::join(LiveInterval &Other, int *LHSValNoAssignments,
   for (unsigned i = 0; i != NumVals; ++i) {
     unsigned LHSValID = LHSValNoAssignments[i];
     if (i != LHSValID ||
-        (NewVNInfo[LHSValID] && NewVNInfo[LHSValID]->parent != this))
+        (NewVNInfo[LHSValID] && NewVNInfo[LHSValID] != getValNumInfo(i)))
       MustMapCurValNos = true;
-
-    // There might be some dead val#, create VNInfo for them.
-    if (i < NumNewVals) {
-      VNInfo *VNI = NewVNInfo[i];
-      if (!VNI) {
-        VNI = new VNInfo(this, i, ~1U, 0);
-        NewVNInfo[i] = VNI;
-      }
-    }
   }
 
   // If we have to apply a mapping to our base interval assignment, rewrite it
@@ -345,27 +340,18 @@ void LiveInterval::join(LiveInterval &Other, int *LHSValNoAssignments,
     OtherAssignments.push_back(RHSValNoAssignments[I->valno->id]);
 
   // Update val# info. Renumber them and make sure they all belong to this
-  // LiveInterval now.
-  for (unsigned i = 0; i != NumVals; ++i) {
-    if (i == NumNewVals)
-      break;
+  // LiveInterval now. Also remove dead val#'s.
+  unsigned NumValNos = 0;
+  for (unsigned i = 0; i < NumNewVals; ++i) {
     VNInfo *VNI = NewVNInfo[i];
-    if (VNI->parent != this || VNI->id != i) {
-      VNI->parent = this;
-      VNI->id = i;  // Renumber val#.
-      valnos[i] = VNI;
+    if (VNI) {
+      if (i >= NumVals)
+        valnos.push_back(VNI);
+      else 
+        valnos[NumValNos] = VNI;
+      VNI->id = NumValNos++;  // Renumber val#.
     }
   }
-  for (unsigned i = NumVals; i < NumNewVals; ++i) {
-    VNInfo *VNI = NewVNInfo[i];
-    if (!VNI)
-      VNI = new VNInfo(this, i, ~1U, 0);
-    else {
-      VNI->parent = this;
-      VNI->id = i;  // Renumber val#.
-    }
-    valnos.push_back(VNI);
-  }
   if (NumNewVals < NumVals)
     valnos.resize(NumNewVals);  // shrinkify
 
@@ -375,6 +361,7 @@ void LiveInterval::join(LiveInterval &Other, int *LHSValNoAssignments,
   for (iterator I = Other.begin(), E = Other.end(); I != E; ++I, ++RangeNo) {
     // Map the valno in the other live range to the current live range.
     I->valno = NewVNInfo[OtherAssignments[RangeNo]];
+    assert(I->valno && "Adding a dead range?");
     InsertPos = addRangeFrom(*I, InsertPos);
   }
 
@@ -400,16 +387,86 @@ void LiveInterval::MergeRangesInAsValue(const LiveInterval &RHS,
 }
 
 
+/// MergeValueInAsValue - Merge all of the live ranges of a specific val#
+/// in RHS into this live interval as the specified value number.
+/// The LiveRanges in RHS are allowed to overlap with LiveRanges in the
+/// current interval, it will replace the value numbers of the overlaped
+/// live ranges with the specified value number.
+void LiveInterval::MergeValueInAsValue(const LiveInterval &RHS,
+                                     const VNInfo *RHSValNo, VNInfo *LHSValNo) {
+  SmallVector<VNInfo*, 4> ReplacedValNos;
+  iterator IP = begin();
+  for (const_iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) {
+    if (I->valno != RHSValNo)
+      continue;
+    unsigned Start = I->start, End = I->end;
+    IP = std::upper_bound(IP, end(), Start);
+    // If the start of this range overlaps with an existing liverange, trim it.
+    if (IP != begin() && IP[-1].end > Start) {
+      if (IP->valno != LHSValNo) {
+        ReplacedValNos.push_back(IP->valno);
+        IP->valno = LHSValNo; // Update val#.
+      }
+      Start = IP[-1].end;
+      // Trimmed away the whole range?
+      if (Start >= End) continue;
+    }
+    // If the end of this range overlaps with an existing liverange, trim it.
+    if (IP != end() && End > IP->start) {
+      if (IP->valno != LHSValNo) {
+        ReplacedValNos.push_back(IP->valno);
+        IP->valno = LHSValNo;  // Update val#.
+      }
+      End = IP->start;
+      // If this trimmed away the whole range, ignore it.
+      if (Start == End) continue;
+    }
+    
+    // Map the valno in the other live range to the current live range.
+    IP = addRangeFrom(LiveRange(Start, End, LHSValNo), IP);
+  }
+
+
+  SmallSet<VNInfo*, 4> Seen;
+  for (unsigned i = 0, e = ReplacedValNos.size(); i != e; ++i) {
+    VNInfo *V1 = ReplacedValNos[i];
+    if (Seen.insert(V1)) {
+      bool isDead = true;
+      for (const_iterator I = begin(), E = end(); I != E; ++I)
+        if (I->valno == V1) {
+          isDead = false;
+          break;
+        }          
+      if (isDead) {
+        // Now that V1 is dead, remove it.  If it is the largest value number,
+        // just nuke it (and any other deleted values neighboring it), otherwise
+        // mark it as ~1U so it can be nuked later.
+        if (V1->id == getNumValNums()-1) {
+          do {
+            VNInfo *VNI = valnos.back();
+            valnos.pop_back();
+            VNI->~VNInfo();
+          } while (valnos.back()->def == ~1U);
+        } else {
+          V1->def = ~1U;
+        }
+      }
+    }
+  }
+}
+
+
 /// MergeInClobberRanges - For any live ranges that are not defined in the
 /// current interval, but are defined in the Clobbers interval, mark them
 /// used with an unknown definition value.
-void LiveInterval::MergeInClobberRanges(const LiveInterval &Clobbers) {
+void LiveInterval::MergeInClobberRanges(const LiveInterval &Clobbers,
+                                        BumpPtrAllocator &VNInfoAllocator) {
   if (Clobbers.begin() == Clobbers.end()) return;
   
   // Find a value # to use for the clobber ranges.  If there is already a value#
   // for unknown values, use it.
   // FIXME: Use a single sentinal number for these!
-  VNInfo *ClobberValNo = getNextValue(~0U, 0);
+  VNInfo *ClobberValNo = getNextValue(~0U, 0, VNInfoAllocator);
   
   iterator IP = begin();
   for (const_iterator I = Clobbers.begin(), E = Clobbers.end(); I != E; ++I) {
@@ -448,7 +505,7 @@ void LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) {
 
   // Make sure V2 is smaller than V1.
   if (V1->id < V2->id) {
-    copyValNumInfo(*V1, *V2);
+    copyValNumInfo(V1, V2);
     std::swap(V1, V2);
   }
 
@@ -494,13 +551,30 @@ void LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) {
     do {
       VNInfo *VNI = valnos.back();
       valnos.pop_back();
-      delete VNI;
+      VNI->~VNInfo();
     } while (valnos.back()->def == ~1U);
   } else {
     V1->def = ~1U;
   }
 }
 
+void LiveInterval::Copy(const LiveInterval &RHS,
+                        BumpPtrAllocator &VNInfoAllocator) {
+  ranges.clear();
+  valnos.clear();
+  preference = RHS.preference;
+  weight = RHS.weight;
+  for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) {
+    const VNInfo *VNI = RHS.getValNumInfo(i);
+    VNInfo *NewVNI = getNextValue(~0U, 0, VNInfoAllocator);
+    copyValNumInfo(NewVNI, VNI);
+  }
+  for (unsigned i = 0, e = RHS.ranges.size(); i != e; ++i) {
+    const LiveRange &LR = RHS.ranges[i];
+    addRange(LiveRange(LR.start, LR.end, getValNumInfo(LR.valno->id)));
+  }
+}
+
 unsigned LiveInterval::getSize() const {
   unsigned Sum = 0;
   for (const_iterator I = begin(), E = end(); I != E; ++I)
@@ -557,6 +631,8 @@ void LiveInterval::print(std::ostream &OS, const MRegisterInfo *MRI) const {
             if (j != ee-1)
               OS << " ";
           }
+          if (vni->hasPHIKill)
+            OS << " phi";
           OS << ")";
         }
       }