Teach the coallescer to coallesce live intervals joined by an arbitrary
authorChris Lattner <sabre@nondot.org>
Tue, 29 Aug 2006 23:18:15 +0000 (23:18 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 29 Aug 2006 23:18:15 +0000 (23:18 +0000)
number of copies, potentially defining live ranges that appear to have
differing value numbers that become identical when coallsced.  Among other
things, this fixes CodeGen/X86/shift-coalesce.ll and PR687.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29968 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/LiveInterval.h
include/llvm/CodeGen/LiveIntervalAnalysis.h
lib/CodeGen/LiveInterval.cpp
lib/CodeGen/LiveIntervalAnalysis.cpp

index c9fef0cd16433c69865e8516fcece833911c13b7..33b2c75e6a2fd36f0e2082be68775cd54ce82379 100644 (file)
@@ -78,8 +78,6 @@ namespace llvm {
     float weight;        // weight of this interval
     Ranges ranges;       // the ranges in which this register is live
   private:
-    unsigned NumValues;  // the number of distinct values in this interval.
-    
     /// InstDefiningValue - This tracks the def index of the instruction that
     /// defines a particular value number in the interval.  This may be ~0,
     /// which is treated as unknown, or ~1, which is a deleted value number.
@@ -87,7 +85,7 @@ namespace llvm {
   public:
 
     LiveInterval(unsigned Reg, float Weight)
-      : reg(Reg), weight(Weight), NumValues(0) {
+      : reg(Reg), weight(Weight) {
     }
 
     typedef Ranges::iterator iterator;
@@ -115,24 +113,24 @@ namespace llvm {
       std::swap(reg, other.reg);
       std::swap(weight, other.weight);
       std::swap(ranges, other.ranges);
-      std::swap(NumValues, other.NumValues);
       std::swap(InstDefiningValue, other.InstDefiningValue);
     }
 
-    bool containsOneValue() const { return NumValues == 1; }
+    bool containsOneValue() const { return InstDefiningValue.size() == 1; }
 
-    unsigned getNumValNums() const { return NumValues; }
+    unsigned getNumValNums() const { return InstDefiningValue.size(); }
     
     /// getNextValue - Create a new value number and return it.  MIIdx specifies
     /// the instruction that defines the value number.
     unsigned getNextValue(unsigned MIIdx) {
       InstDefiningValue.push_back(MIIdx);
-      return NumValues++;
+      return InstDefiningValue.size()-1;
     }
     
     /// getInstForValNum - Return the machine instruction index that defines the
     /// specified value number.
     unsigned getInstForValNum(unsigned ValNo) const {
+      assert(ValNo < InstDefiningValue.size());
       return InstDefiningValue[ValNo];
     }
     
@@ -189,11 +187,6 @@ namespace llvm {
     /// contains the specified index, or end() if there is none.
     iterator FindLiveRangeContaining(unsigned Idx);
     
-    /// joinable - Two intervals are joinable if the either don't overlap at all
-    /// or if the destination of the copy is a single assignment value, and it
-    /// only overlaps with one value in the source interval.
-    bool joinable(const LiveInterval& other, unsigned CopyIdx) const;
-
     /// getOverlapingRanges - Given another live interval which is defined as a
     /// copy from this one, return a list of all of the live ranges where the
     /// two overlap and have different value numbers.
@@ -218,11 +211,12 @@ namespace llvm {
       addRangeFrom(LR, ranges.begin());
     }
 
-    /// join - Join two live intervals (this, and other) together.  This
-    /// operation is the result of a copy instruction in the source program,
-    /// that occurs at index 'CopyIdx' that copies from 'other' to 'this'.  This
-    /// destroys 'other'.
-    void join(LiveInterval& other, unsigned CopyIdx);
+    /// 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 join(LiveInterval &Other, int *ValNoAssignments,
+              int *RHSValNoAssignments,
+              SmallVector<unsigned, 16> &NewInstDefiningValue);
 
 
     /// removeRange - Remove the specified range from this interval.  Note that
index 5c19107e1c8caf232f13eef7e9fa122db61f732b..845a4b071699e626a495a23097e42ebe27598c6f 100644 (file)
@@ -174,6 +174,13 @@ namespace llvm {
     /// it may be possible if other things get coallesced.
     bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg);
     
+    /// JoinIntervals - Attempt to join these two intervals.  On failure, this
+    /// returns false.  Otherwise, if one of the intervals being joined is a
+    /// physreg, this method always canonicalizes DestInt to be it.  The output
+    /// "SrcInt" will not have been modified, so we can use this information
+    /// below to update aliases.
+    bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS);
+    
     /// handleRegisterDef - update intervals for a register def
     /// (calls handlePhysicalRegisterDef and
     /// handleVirtualRegisterDef)
@@ -200,7 +207,7 @@ namespace llvm {
 
 
     bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB,
-                              MachineInstr *CopyMI, unsigned CopyIdx);
+                              MachineInstr *CopyMI);
 
     bool overlapsAliases(const LiveInterval *lhs,
                          const LiveInterval *rhs) const;
index 7f16b31823849058a1432bdcc31d9614ebf4bef3..8be967792915f29df9cc08a95ae0bf950fe580cd 100644 (file)
@@ -101,101 +101,6 @@ bool LiveInterval::overlapsFrom(const LiveInterval& other,
   return false;
 }
 
-/// NontrivialOverlap - Check to see if the two live ranges specified by i and j
-/// overlap.  If so, check to see if they have value numbers that are not 
-/// iIdx/jIdx respectively.  If both conditions are true, return true.
-static inline bool NontrivialOverlap(const LiveRange &I, const LiveRange &J,
-                                     unsigned iIdx, unsigned jIdx) {
-  if (I.start == J.start) {
-    // If this is not the allowed value merge, we cannot join.
-    if (I.ValId != iIdx || J.ValId != jIdx)
-      return true;
-  } else if (I.start < J.start) {
-    if (I.end > J.start && (I.ValId != iIdx || J.ValId != jIdx)) {
-      return true;
-    }
-  } else {
-    if (J.end > I.start && (I.ValId != iIdx || J.ValId != jIdx))
-      return true;
-  }
-  
-  return false;
-}
-
-/// joinable - Two intervals are joinable if the either don't overlap at all
-/// or if the destination of the copy is a single assignment value, and it
-/// only overlaps with one value in the source interval.
-bool LiveInterval::joinable(const LiveInterval &other, unsigned CopyIdx) const {
-  const LiveRange *SourceLR = other.getLiveRangeContaining(CopyIdx-1);
-  const LiveRange *DestLR = getLiveRangeContaining(CopyIdx);
-  assert(SourceLR && DestLR && "Not joining due to a copy?");
-  unsigned OtherValIdx = SourceLR->ValId;
-  unsigned ThisValIdx = DestLR->ValId;
-
-  Ranges::const_iterator i = ranges.begin();
-  Ranges::const_iterator ie = ranges.end();
-  Ranges::const_iterator j = other.ranges.begin();
-  Ranges::const_iterator je = other.ranges.end();
-
-  if (i->start < j->start) {
-    i = std::upper_bound(i, ie, j->start);
-    if (i != ranges.begin()) --i;
-  } else if (j->start < i->start) {
-    j = std::upper_bound(j, je, i->start);
-    if (j != other.ranges.begin()) --j;
-  }
-
-  while (i != ie && j != je) {
-    if (NontrivialOverlap(*i, *j, ThisValIdx, OtherValIdx))
-      return false;
-    
-    if (i->end < j->end)
-      ++i;
-    else
-      ++j;
-  }
-
-  return true;
-}
-
-/// getOverlapingRanges - Given another live interval which is defined as a
-/// copy from this one, return a list of all of the live ranges where the
-/// two overlap and have different value numbers.
-void LiveInterval::getOverlapingRanges(const LiveInterval &other, 
-                                       unsigned CopyIdx,
-                                       std::vector<LiveRange*> &Ranges) {
-  const LiveRange *SourceLR = getLiveRangeContaining(CopyIdx-1);
-  const LiveRange *DestLR = other.getLiveRangeContaining(CopyIdx);
-  assert(SourceLR && DestLR && "Not joining due to a copy?");
-  unsigned OtherValIdx = SourceLR->ValId;
-  unsigned ThisValIdx = DestLR->ValId;
-  
-  Ranges::iterator i = ranges.begin();
-  Ranges::iterator ie = ranges.end();
-  Ranges::const_iterator j = other.ranges.begin();
-  Ranges::const_iterator je = other.ranges.end();
-  
-  if (i->start < j->start) {
-    i = std::upper_bound(i, ie, j->start);
-    if (i != ranges.begin()) --i;
-  } else if (j->start < i->start) {
-    j = std::upper_bound(j, je, i->start);
-    if (j != other.ranges.begin()) --j;
-  }
-  
-  while (i != ie && j != je) {
-    if (NontrivialOverlap(*i, *j, ThisValIdx, OtherValIdx))
-      Ranges.push_back(&*i);
-    
-    if (i->end < j->end)
-      ++i;
-    else
-      ++j;
-  }
-}
-
-
-
 /// extendIntervalEndTo - This method is used when we want to extend the range
 /// specified by I to end at the specified endpoint.  To do this, we should
 /// merge and eliminate all ranges that this will overlap with.  The iterator is
@@ -361,7 +266,7 @@ LiveInterval::FindLiveRangeContaining(unsigned Idx) const {
 LiveInterval::iterator 
 LiveInterval::FindLiveRangeContaining(unsigned Idx) {
   iterator It = std::upper_bound(begin(), end(), Idx);
-  if (It != ranges.begin()) {
+  if (It != begin()) {
     --It;
     if (It->contains(Idx))
       return It;
@@ -370,10 +275,13 @@ LiveInterval::FindLiveRangeContaining(unsigned Idx) {
   return end();
 }
 
-/// join - Join two live intervals (this, and other) together.  This operation
-/// is the result of a copy instruction in the source program, that occurs at
-/// index 'CopyIdx' that copies from 'Other' to 'this'.
-void LiveInterval::join(LiveInterval &Other, unsigned CopyIdx) {
+/// 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, 
+                        SmallVector<unsigned, 16> &NewInstDefiningValue) {
+  
   // Try to do the least amount of work possible.  In particular, if there are
   // more liverange chunks in the other set than there are in the 'this' set,
   // swap sets to merge the fewest chunks in possible.
@@ -385,39 +293,61 @@ void LiveInterval::join(LiveInterval &Other, unsigned CopyIdx) {
       MRegisterInfo::isVirtualRegister(reg)) ||
       MRegisterInfo::isPhysicalRegister(Other.reg)) {
     swap(Other);
-    std::swap(ThisOffs, OtherOffs);
+    std::swap(LHSValNoAssignments, RHSValNoAssignments);
+  }
+
+  // Determine if any of our live range values are mapped.  This is uncommon, so
+  // we want to avoid the interval scan if not.
+  bool MustMapCurValNos = false;
+  for (unsigned i = 0, e = getNumValNums(); i != e; ++i) {
+    if (InstDefiningValue[i] == ~2U) continue;  // tombstone value #
+    if (i != (unsigned)LHSValNoAssignments[i]) {
+      MustMapCurValNos = true;
+      break;
+    }
+  }
+  
+  // If we have to apply a mapping to our base interval assignment, rewrite it
+  // now.
+  if (MustMapCurValNos) {
+    // Map the first live range.
+    iterator OutIt = begin();
+    OutIt->ValId = LHSValNoAssignments[OutIt->ValId];
+    ++OutIt;
+    for (iterator I = OutIt, E = end(); I != E; ++I) {
+      OutIt->ValId = LHSValNoAssignments[I->ValId];
+      
+      // If this live range has the same value # as its immediate predecessor,
+      // and if they are neighbors, remove one LiveRange.  This happens when we
+      // have [0,3:0)[4,7:1) and map 0/1 onto the same value #.
+      if (OutIt->ValId == (OutIt-1)->ValId && (OutIt-1)->end == OutIt->start) {
+        (OutIt-1)->end = OutIt->end;
+      } else {
+        if (I != OutIt) {
+          OutIt->start = I->start;
+          OutIt->end = I->end;
+        }
+        
+        // Didn't merge, on to the next one.
+        ++OutIt;
+      }
+    }
+    
+    // If we merge some live ranges, chop off the end.
+    ranges.erase(OutIt, end());
   }
   
-  const LiveRange *SourceLR = Other.getLiveRangeContaining(CopyIdx-OtherOffs);
-  const LiveRange *DestLR = getLiveRangeContaining(CopyIdx-ThisOffs);
-  assert(SourceLR && DestLR && "Not joining due to a copy?");
-  unsigned MergedSrcValIdx = SourceLR->ValId;
-  unsigned MergedDstValIdx = DestLR->ValId;
-
-  // Join the ranges of other into the ranges of this interval.
-  std::map<unsigned, unsigned> Dst2SrcIdxMap;
+  // Okay, now insert the RHS live ranges into the LHS.
   iterator InsertPos = begin();
   for (iterator I = Other.begin(), E = Other.end(); I != E; ++I) {
     // Map the ValId in the other live range to the current live range.
-    if (I->ValId == MergedSrcValIdx)
-      I->ValId = MergedDstValIdx;
-    else {
-      unsigned &NV = Dst2SrcIdxMap[I->ValId];
-      if (NV == 0) NV = getNextValue(Other.getInstForValNum(I->ValId));
-      I->ValId = NV;
-    }
-
+    I->ValId = RHSValNoAssignments[I->ValId];
     InsertPos = addRangeFrom(*I, InsertPos);
   }
-  
-  // Update the value number information for the value number defined by the
-  // copy.  The copy is about to be removed, so ensure that the value is defined
-  // by whatever the other value is defined by.
-  if (InstDefiningValue[MergedDstValIdx] == CopyIdx) {
-    InstDefiningValue[MergedDstValIdx] =
-      Other.InstDefiningValue[MergedSrcValIdx];
-  }
-  
+
+  InstDefiningValue.clear();
+  InstDefiningValue.append(NewInstDefiningValue.begin(), 
+                           NewInstDefiningValue.end());
   weight += Other.weight;
 }
 
@@ -511,10 +441,9 @@ void LiveInterval::MergeValueNumberInto(unsigned V1, unsigned V2) {
   // 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 == NumValues-1) {
+  if (V1 == getNumValNums()-1) {
     do {
       InstDefiningValue.pop_back();
-      --NumValues;
     } while (InstDefiningValue.back() == ~1U);
   } else {
     InstDefiningValue[V1] = ~1U;
@@ -548,9 +477,9 @@ void LiveInterval::print(std::ostream &OS, const MRegisterInfo *MRI) const {
   }
   
   // Print value number info.
-  if (NumValues) {
+  if (getNumValNums()) {
     OS << "  ";
-    for (unsigned i = 0; i != NumValues; ++i) {
+    for (unsigned i = 0; i != getNumValNums(); ++i) {
       if (i) OS << " ";
       OS << i << "@";
       if (InstDefiningValue[i] == ~0U) {
index 4f34881cf0e49f3f128fee16064a3e244593a2b0..a26feb3023c1415c1817d4e7fc1b881edcf40ae7 100644 (file)
@@ -629,8 +629,9 @@ void LiveIntervals::computeIntervals() {
 /// This returns true if an interval was modified.
 ///
 bool LiveIntervals::AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB,
-                                         MachineInstr *CopyMI,
-                                         unsigned CopyIdx) {
+                                         MachineInstr *CopyMI) {
+  unsigned CopyIdx = getDefIndex(getInstructionIndex(CopyMI));
+
   // BValNo is a value number in B that is defined by a copy from A.  'B3' in
   // the example above.
   LiveInterval::iterator BLR = IntB.FindLiveRangeContaining(CopyIdx);
@@ -768,34 +769,22 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI,
         std::cerr << " and "; DestInt.print(std::cerr, mri_);
         std::cerr << ": ");
     
-  // If two intervals contain a single value and are joined by a copy, it
-  // does not matter if the intervals overlap, they can always be joined.
+  // Okay, attempt to join these two intervals.  On failure, this returns false.
+  // Otherwise, if one of the intervals being joined is a physreg, this method
+  // always canonicalizes DestInt to be it.  The output "SrcInt" will not have
+  // been modified, so we can use this information below to update aliases.
+  if (!JoinIntervals(DestInt, SrcInt)) {
+    // Coallescing failed.
+    
+    // If we can eliminate the copy without merging the live ranges, do so now.
+    if (AdjustCopiesBackFrom(SrcInt, DestInt, CopyMI))
+      return true;
 
-  bool Joinable = SrcInt.containsOneValue() && DestInt.containsOneValue();
-  
-  unsigned MIDefIdx = getDefIndex(getInstructionIndex(CopyMI));
-  
-  // If the intervals think that this is joinable, do so now.
-  if (!Joinable && DestInt.joinable(SrcInt, MIDefIdx))
-    Joinable = true;
-  
-  // If DestInt is actually a copy from SrcInt (which we know) that is used
-  // to define another value of SrcInt, we can change the other range of
-  // SrcInt to be the value of the range that defines DestInt, simplying the
-  // interval an promoting coallescing.
-  if (!Joinable && AdjustCopiesBackFrom(SrcInt, DestInt, CopyMI, MIDefIdx))
-    return true;
-  
-  if (!Joinable) {
+    // Otherwise, we are unable to join the intervals.
     DEBUG(std::cerr << "Interference!\n");
     return false;
   }
 
-  // Okay, we can join these two intervals.  If one of the intervals being
-  // joined is a physreg, this method always canonicalizes DestInt to be it.
-  // The output "SrcInt" will not have been modified.
-  DestInt.join(SrcInt, MIDefIdx);
-
   bool Swapped = SrcReg == DestInt.reg;
   if (Swapped)
     std::swap(SrcReg, DstReg);
@@ -823,6 +812,182 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI,
   return true;
 }
 
+/// ComputeUltimateVN - Assuming we are going to join two live intervals,
+/// compute what the resultant value numbers for each value in the input two
+/// ranges will be.  This is complicated by copies between the two which can
+/// and will commonly cause multiple value numbers to be merged into one.
+///
+/// VN is the value number that we're trying to resolve.  InstDefiningValue
+/// keeps track of the new InstDefiningValue assignment for the result
+/// LiveInterval.  ThisFromOther/OtherFromThis are sets that keep track of
+/// whether a value in this or other is a copy from the opposite set.
+/// ThisValNoAssignments/OtherValNoAssignments keep track of value #'s that have
+/// already been assigned.
+///
+/// ThisFromOther[x] - If x is defined as a copy from the other interval, this
+/// contains the value number the copy is from.
+///
+static unsigned ComputeUltimateVN(unsigned VN,
+                                  SmallVector<unsigned, 16> &InstDefiningValue,
+                                  SmallVector<int, 16> &ThisFromOther,
+                                  SmallVector<int, 16> &OtherFromThis,
+                                  SmallVector<int, 16> &ThisValNoAssignments,
+                                  SmallVector<int, 16> &OtherValNoAssignments,
+                                  LiveInterval &ThisLI, LiveInterval &OtherLI) {
+  // If the VN has already been computed, just return it.
+  if (ThisValNoAssignments[VN] >= 0)
+    return ThisValNoAssignments[VN];
+  assert(ThisValNoAssignments[VN] != -2 && "FIXME: Cyclic case, handle it!");
+  
+  // If this val is not a copy from the other val, then it must be a new value
+  // number in the destination.
+  int OtherValNo = ThisFromOther[VN];
+  if (OtherValNo == -1) {
+    InstDefiningValue.push_back(ThisLI.getInstForValNum(VN));
+    return ThisValNoAssignments[VN] = InstDefiningValue.size()-1;
+  }
+
+  // Otherwise, this *is* a copy from the RHS.  Mark this value number as
+  // currently being computed, then ask what the ultimate value # of the other
+  // value is.
+  ThisValNoAssignments[VN] = -2;
+  unsigned UltimateVN =
+    ComputeUltimateVN(OtherValNo, InstDefiningValue,
+                      OtherFromThis, ThisFromOther,
+                      OtherValNoAssignments, ThisValNoAssignments,
+                      OtherLI, ThisLI);
+  return ThisValNoAssignments[VN] = UltimateVN;
+}
+
+
+/// JoinIntervals - Attempt to join these two intervals.  On failure, this
+/// returns false.  Otherwise, if one of the intervals being joined is a
+/// physreg, this method always canonicalizes LHS to be it.  The output
+/// "RHS" will not have been modified, so we can use this information
+/// below to update aliases.
+bool LiveIntervals::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS) {
+  // Loop over the value numbers of the LHS, seeing if any are defined from the
+  // RHS.
+  SmallVector<int, 16> LHSValsDefinedFromRHS;
+  LHSValsDefinedFromRHS.resize(LHS.getNumValNums(), -1);
+  for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) {
+    unsigned ValInst = LHS.getInstForValNum(VN);
+    if (ValInst == ~0U || ValInst == ~1U)
+      continue;
+    
+    // If the instruction defining the LHS's value is a copy.
+    MachineInstr *ValInstMI = getInstructionFromIndex(ValInst);
+    
+    // If the value number is not defined by a copy instruction, ignore it.
+    unsigned SrcReg, DstReg;
+    if (!tii_->isMoveInstr(*ValInstMI, SrcReg, DstReg))
+      continue;
+    
+    // DstReg is known to be a register in the LHS interval.  If the src is from
+    // the RHS interval, we can use its value #.
+    if (rep(SrcReg) != RHS.reg)
+      continue;
+    
+    // Figure out the value # from the RHS.
+    LHSValsDefinedFromRHS[VN] = RHS.getLiveRangeContaining(ValInst-1)->ValId;
+  }
+  
+  // Loop over the value numbers of the RHS, seeing if any are defined from the
+  // LHS.
+  SmallVector<int, 16> RHSValsDefinedFromLHS;
+  RHSValsDefinedFromLHS.resize(RHS.getNumValNums(), -1);
+  for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) {
+    unsigned ValInst = RHS.getInstForValNum(VN);
+    if (ValInst == ~0U || ValInst == ~1U)
+      continue;
+    
+    // If the instruction defining the RHS's value is a copy.
+    MachineInstr *ValInstMI = getInstructionFromIndex(ValInst);
+    
+    // If the value number is not defined by a copy instruction, ignore it.
+    unsigned SrcReg, DstReg;
+    if (!tii_->isMoveInstr(*ValInstMI, SrcReg, DstReg))
+      continue;
+    
+    // DstReg is known to be a register in the RHS interval.  If the src is from
+    // the LHS interval, we can use its value #.
+    if (rep(SrcReg) != LHS.reg)
+      continue;
+    
+    // Figure out the value # from the LHS.
+    RHSValsDefinedFromLHS[VN] = LHS.getLiveRangeContaining(ValInst-1)->ValId;
+  }
+  
+  // Now that we know the value mapping, compute the final value assignment,
+  // assuming that the live ranges can be coallesced.
+  SmallVector<int, 16> LHSValNoAssignments;
+  SmallVector<int, 16> RHSValNoAssignments;
+  SmallVector<unsigned, 16> InstDefiningValue;
+  LHSValNoAssignments.resize(LHS.getNumValNums(), -1);
+  RHSValNoAssignments.resize(RHS.getNumValNums(), -1);
+  
+  // Compute ultimate value numbers for the LHS and RHS values.
+  for (unsigned VN = 0, e = LHS.getNumValNums(); VN != e; ++VN) {
+    if (LHS.getInstForValNum(VN) == ~2U) continue;
+    ComputeUltimateVN(VN, InstDefiningValue,
+                      LHSValsDefinedFromRHS, RHSValsDefinedFromLHS,
+                      LHSValNoAssignments, RHSValNoAssignments, LHS, RHS);
+  }
+  for (unsigned VN = 0, e = RHS.getNumValNums(); VN != e; ++VN) {
+    if (RHS.getInstForValNum(VN) == ~2U) continue;
+    ComputeUltimateVN(VN, InstDefiningValue,
+                      RHSValsDefinedFromLHS, LHSValsDefinedFromRHS,
+                      RHSValNoAssignments, LHSValNoAssignments, RHS, LHS);
+  }
+  
+  // Armed with the mappings of LHS/RHS values to ultimate values, walk the
+  // interval lists to see if these intervals are coallescable.
+  LiveInterval::const_iterator I = LHS.begin();
+  LiveInterval::const_iterator IE = LHS.end();
+  LiveInterval::const_iterator J = RHS.begin();
+  LiveInterval::const_iterator JE = RHS.end();
+  
+  // Skip ahead until the first place of potential sharing.
+  if (I->start < J->start) {
+    I = std::upper_bound(I, IE, J->start);
+    if (I != LHS.begin()) --I;
+  } else if (J->start < I->start) {
+    J = std::upper_bound(J, JE, I->start);
+    if (J != RHS.begin()) --J;
+  }
+  
+  while (1) {
+    // Determine if these two live ranges overlap.
+    bool Overlaps;
+    if (I->start < J->start) {
+      Overlaps = I->end > J->start;
+    } else {
+      Overlaps = J->end > I->start;
+    }
+
+    // If so, check value # info to determine if they are really different.
+    if (Overlaps) {
+      // If the live range overlap will map to the same value number in the
+      // result liverange, we can still coallesce them.  If not, we can't.
+      if (LHSValNoAssignments[I->ValId] != RHSValNoAssignments[J->ValId])
+        return false;
+    }
+    
+    if (I->end < J->end) {
+      ++I;
+      if (I == IE) break;
+    } else {
+      ++J;
+      if (J == JE) break;
+    }
+  }
+
+  // If we get here, we know that we can coallesce the live ranges.  Ask the
+  // intervals to coallesce themselves now.
+  LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0],
+           InstDefiningValue);
+  return true;
+}
 
 
 namespace {