[llvm-commits] [llvm] r150909 - /llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp

Lang Hames lhames at gmail.com
Sat Feb 18 19:00:30 PST 2012


Author: lhames
Date: Sat Feb 18 21:00:30 2012
New Revision: 150909

URL: http://llvm.org/viewvc/llvm-project?rev=150909&view=rev
Log:
Defer sanity checks on live intervals until after all have been updated. Hold (LiveInterval, LiveRange) pairs to update, rather than vregs.

Modified:
    llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp

Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=150909&r1=150908&r2=150909&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Sat Feb 18 21:00:30 2012
@@ -1033,89 +1033,82 @@
   const TargetRegisterInfo& TRI;
   SlotIndex NewIdx;
 
+  typedef std::pair<LiveInterval*, LiveRange*> IntRangePair;
+  typedef DenseSet<IntRangePair> RangeSet;
+
 public:
   HMEditor(LiveIntervals& LIS, const MachineRegisterInfo& MRI,
            const TargetRegisterInfo& TRI, SlotIndex NewIdx)
     : LIS(LIS), MRI(MRI), TRI(TRI), NewIdx(NewIdx) {}
 
-  // Update lr to be defined at NewIdx. Preserves lr.
-  void moveDef(LiveRange& LR, LiveInterval& LI) {
-    LR.start = NewIdx.getRegSlot();
-    LR.valno->def = NewIdx.getRegSlot();
-    assert(intervalRangesSane(LI) && "Broke live interval moving def.");
-  }
-
-  // Removes lr from li, inserting a new dead-def range starting at NewIdx.
-  void moveDeadDefOrEC(LiveRange& LR, LiveInterval& LI, bool isEC) {
-    LiveRange T(LR);
-    T.start = NewIdx.getRegSlot(isEC);
-    T.valno->def = NewIdx.getRegSlot(isEC);
-    T.end = isEC ? NewIdx.getRegSlot() : NewIdx.getDeadSlot();
-    LI.removeRange(LR);
-    LI.addRange(T);
-    assert(intervalRangesSane(LI) && "Broke live interval moving dead def.");
-  }
-
-  void moveUseDown(SlotIndex OldIdx, LiveRange& LR, LiveInterval& LI,
-                   const MachineBasicBlock* MBB) {
-    bool LiveThrough = LR.end > OldIdx.getRegSlot();
-    if (!LiveThrough) {
-      // Easy fix - just update the range endpoint.
-      LR.end = NewIdx.getRegSlot();
-    } else {
-      bool LiveOut = LR.end >= LIS.getSlotIndexes()->getMBBEndIdx(MBB);
-      if (!LiveOut) {
-        moveKillFlags(LI.reg, LR.end, NewIdx);
-        LR.end = NewIdx.getRegSlot();
-      }
-    }
-    assert(intervalRangesSane(LI) && "Broke live interval moving use.");
-  }
-
-  void moveUseUp(SlotIndex OldIdx, LiveRange& LR, LiveInterval& LI) {
-    bool LiveThrough = LR.end > OldIdx.getRegSlot();
-    if (LiveThrough)
-      return; // If we moving up and live through there's nothing to do.
-    SlotIndex LastUseInRange = NewIdx.getRegSlot();
-    for (MachineRegisterInfo::use_nodbg_iterator
-           UI = MRI.use_nodbg_begin(LI.reg),
-           UE = MRI.use_nodbg_end();
-         UI != UE; ++UI) {
-      const MachineInstr* MI = &*UI;
-      const MachineOperand& MO = UI.getOperand();
-      SlotIndex InstSlot = LIS.getSlotIndexes()->getInstructionIndex(MI);
-      SlotIndex OpSlot = InstSlot.getRegSlot(MO.isEarlyClobber());
-      if (OpSlot > LastUseInRange && OpSlot < OldIdx)
-        LastUseInRange = OpSlot;
-    }
+  // Update intervals for all operands of MI from OldIdx to NewIdx.
+  // This assumes that MI used to be at OldIdx, and now resides at
+  // NewIdx.
+  void moveAllOperandsFrom(MachineInstr* MI, SlotIndex OldIdx) {
+    // Collect the operands.
+    RangeSet Entering, Internal, Exiting;
+    collectRanges(MI, Entering, Internal, Exiting, OldIdx);
 
-    // If we found a new instr endpoint update the kill flags.
-    if (LastUseInRange != NewIdx.getRegSlot())
-      moveKillFlags(LI.reg, NewIdx, LastUseInRange);
+    moveAllEnteringFrom(OldIdx, Entering);
+    moveAllInternalFrom(OldIdx, Internal);
+    moveAllExitingFrom(OldIdx, Exiting);
 
-    // Fix up the range end.
-    LR.end = LastUseInRange;
+#ifndef NDEBUG
+    LIValidator validator;
+    std::for_each(Entering.begin(), Entering.end(), validator);
+    std::for_each(Internal.begin(), Internal.end(), validator);
+    std::for_each(Exiting.begin(), Exiting.end(), validator);
+    assert(validator.rangesOk() && "moveOperandsFrom broke liveness.");
+#endif
 
-    assert(intervalRangesSane(LI) && "Broke live interval moving use.");
+// TODO: Update reg mask slots.
+//      assert((OldIdx == SlotIndex() || !MO.isRegMask()) &&
+//             "Unexpected RegMask operand.");
+//       if (MO.isRegMask()) {
+//         updateRegMaskSlots(OldIdx);
+//         continue;
+//       }
   }
 
-  // Update intervals for all operands of mi from oldIndex to newIndex.
-  void moveAllOperandsFrom(MachineInstr* MI, SlotIndex OldIdx) {
-    // Figure out the direction we're moving.
-    bool MovingUp = NewIdx < OldIdx;
+private:
 
-    // Collect the operands.
-    DenseSet<unsigned> Uses, Defs, DeadDefs, ECs;
+#ifndef NDEBUG
+  class LIValidator {
+  private:
+    DenseSet<const LiveInterval*> Checked, Bogus;
+  public:
+    void operator()(const IntRangePair& P) {
+      const LiveInterval* LI = P.first;
+      if (Checked.count(LI))
+        return;
+      Checked.insert(LI);
+      if (LI->empty())
+        return;
+      SlotIndex LastEnd = LI->begin()->start;
+      for (LiveInterval::const_iterator LRI = LI->begin(), LRE = LI->end();
+           LRI != LRE; ++LRI) {
+        const LiveRange& LR = *LRI;
+        if (LastEnd > LR.start || LR.start >= LR.end)
+          Bogus.insert(LI);
+        LastEnd = LR.end;
+      }
+    }
+
+    bool rangesOk() const {
+      return Bogus.empty();
+    }
+  };
+#endif
+
+  // Collect IntRangePairs for all operands of MI that may need fixing.
+  // Treat's MI's index as OldIdx (regardless of what it is in SlotIndexes'
+  // maps).
+  void collectRanges(MachineInstr* MI, RangeSet& Entering, RangeSet& Internal,
+                     RangeSet& Exiting, SlotIndex OldIdx) {
     for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
                                     MOE = MI->operands_end();
          MOI != MOE; ++MOI) {
       const MachineOperand& MO = *MOI;
-
-      if (MO.isRegMask()) {
-        updateRegMaskSlots(OldIdx);
-        continue;
-      }
-
       if (!MO.isReg() || MO.getReg() == 0)
         continue;
 
@@ -1128,56 +1121,34 @@
           (TargetRegisterInfo::isPhysicalRegister(Reg) && LIS.isReserved(Reg)))
         continue;
 
-      if (MO.readsReg() && !ECs.count(Reg)) {
-        Uses.insert(Reg);
+      LiveInterval* LI = &LIS.getInterval(Reg);
+
+      if (MO.readsReg()) {
+        LiveRange* LR = LI->getLiveRangeContaining(OldIdx);
+        if (LR != 0)
+          Entering.insert(std::make_pair(LI, LR));
       }
       if (MO.isDef()) {
-        if (MO.isDead()) {
-          assert(!Defs.count(Reg) && "Can't mix defs with dead-defs.");
-          DeadDefs.insert(Reg);
-        } else if (MO.isEarlyClobber()) {
-          Uses.erase(Reg);
-          ECs.insert(Reg);
+        if (MO.isEarlyClobber()) {
+          LiveRange* LR = LI->getLiveRangeContaining(OldIdx.getRegSlot(true));
+          assert(LR != 0 && "No EC range?");
+          if (LR->end > OldIdx.getDeadSlot())
+            Exiting.insert(std::make_pair(LI, LR));
+          else
+            Internal.insert(std::make_pair(LI, LR));         
+        } else if (MO.isDead()) {
+          LiveRange* LR = LI->getLiveRangeContaining(OldIdx.getRegSlot());
+          assert(LR != 0 && "No dead-def range?");
+          Internal.insert(std::make_pair(LI, LR));
         } else {
-          assert(!DeadDefs.count(Reg) && "Can't mix defs with dead-defs.");
-          Defs.insert(Reg);
+          LiveRange* LR = LI->getLiveRangeContaining(OldIdx.getDeadSlot());
+          assert(LR && LR->end > OldIdx.getDeadSlot() &&
+                 "Non-dead-def should have live range exiting.");
+          Exiting.insert(std::make_pair(LI, LR));
         }
       }
     }
-
-    if (MovingUp) {
-      moveUsesUp(OldIdx, Uses);
-      moveECs(OldIdx, ECs);
-      moveDeadDefs(OldIdx, DeadDefs);
-      moveDefs(OldIdx, Defs);
-    } else {
-      moveDefs(OldIdx, Defs);
-      moveDeadDefs(OldIdx, DeadDefs);
-      moveECs(OldIdx, ECs);
-      moveUsesDown(OldIdx, Uses, MI->getParent());
-    }
-  }
-
-private:
-
-#ifndef NDEBUG
-    bool intervalRangesSane(const LiveInterval& LI) {
-    if (LI.empty()) {
-      return true;
-    }
-
-    SlotIndex LastEnd = LI.begin()->start;
-    for (LiveInterval::const_iterator LRI = LI.begin(), LRE = LI.end();
-         LRI != LRE; ++LRI) {
-      const LiveRange& LR = *LRI;
-      if (LastEnd > LR.start || LR.start >= LR.end)
-        return false;
-      LastEnd = LR.end;
-    }
-
-    return true;
   }
-#endif
 
   void moveKillFlags(unsigned reg, SlotIndex OldIdx, SlotIndex newKillIdx) {
     MachineInstr* OldKillMI = LIS.getInstructionFromIndex(OldIdx);
@@ -1190,73 +1161,6 @@
     NewKillMI->addRegisterKilled(reg, &TRI);
   }
 
-  template <typename DefSetT>
-  void moveDefs(SlotIndex OldIdx, const DefSetT& Defs) {
-    typedef typename DefSetT::const_iterator DefItr;
-    for (DefItr DI = Defs.begin(), DE = Defs.end(); DI != DE; ++DI) {
-      unsigned Def = *DI;
-      LiveInterval& LI = LIS.getInterval(Def);
-      LiveRange* LR = LI.getLiveRangeContaining(OldIdx.getRegSlot());
-      assert(LR != 0 && "No range?");
-      moveDef(*LR, LI);
-    }
-  }
-
-  template <typename DeadDefSetT>
-  void moveDeadDefs(SlotIndex OldIdx, const DeadDefSetT& DeadDefs) {
-    typedef typename DeadDefSetT::const_iterator DeadDefItr;
-    for (DeadDefItr DI = DeadDefs.begin(),DE = DeadDefs.end(); DI != DE; ++DI) {
-      unsigned DeadDef = *DI;
-      LiveInterval& LI = LIS.getInterval(DeadDef);
-      LiveRange* LR = LI.getLiveRangeContaining(OldIdx.getRegSlot());
-      assert(LR != 0 && "No range for dead def?");
-      assert(LR->start == OldIdx.getRegSlot() && "Bad dead range start?");
-      assert(LR->end == OldIdx.getDeadSlot() && "Bad dead range end?");
-      assert(LR->valno->def == OldIdx.getRegSlot() && "Bad dead valno def.");
-      moveDeadDefOrEC(*LR, LI, false);
-    }
-  }
-
-  template <typename ECSetT>
-  void moveECs(SlotIndex OldIdx, const ECSetT& ECs) {
-    typedef typename ECSetT::const_iterator ECItr;
-    for (ECItr EI = ECs.begin(), EE = ECs.end(); EI != EE; ++EI) {
-      unsigned EC = *EI;
-      LiveInterval& LI = LIS.getInterval(EC);
-      LiveRange* LR = LI.getLiveRangeContaining(OldIdx.getRegSlot(true));
-      assert(LR != 0 && "No range for early clobber?");
-      assert(LR->start == OldIdx.getRegSlot(true) && "Bad EC range start?");
-      assert(LR->end == OldIdx.getRegSlot() && "Bad EC range end.");
-      assert(LR->valno->def == OldIdx.getRegSlot(true) && "Bad EC valno def.");
-      moveDeadDefOrEC(*LR, LI, true);
-    }
-  }
-
-  template <typename UsesetT>
-  void moveUsesUp(SlotIndex OldIdx, const UsesetT &Uses) {
-    typedef typename UsesetT::const_iterator UseItr;
-    for (UseItr UI = Uses.begin(), UE = Uses.end(); UI != UE; ++UI) {
-      unsigned Use = *UI;
-      LiveInterval& LI = LIS.getInterval(Use);
-      LiveRange* LR = LI.getLiveRangeBefore(OldIdx.getRegSlot());
-      assert(LR != 0 && "No range for use?");
-      moveUseUp(OldIdx, *LR, LI);
-    }
-  }
-
-  template <typename UsesetT>
-  void moveUsesDown(SlotIndex OldIdx, const UsesetT &Uses,
-                    const MachineBasicBlock* MBB) {
-    typedef typename UsesetT::const_iterator UseItr;
-    for (UseItr UI = Uses.begin(), UE = Uses.end(); UI != UE; ++UI) {
-      unsigned Use = *UI;
-      LiveInterval& LI = LIS.getInterval(Use);
-      LiveRange* LR = LI.getLiveRangeBefore(OldIdx.getRegSlot());
-      assert(LR != 0 && "No range for use?");
-      moveUseDown(OldIdx, *LR, LI, MBB);
-    }
-  }
-
   void updateRegMaskSlots(SlotIndex OldIdx) {
     SmallVectorImpl<SlotIndex>::iterator RI =
       std::lower_bound(LIS.RegMaskSlots.begin(), LIS.RegMaskSlots.end(),
@@ -1266,6 +1170,101 @@
     assert(*prior(RI) < *RI && *RI < *next(RI) &&
            "RegSlots out of order. Did you move one call across another?");
   }
+
+  // Return the last use of reg between NewIdx and OldIdx.
+  SlotIndex findLastUseBefore(unsigned Reg, SlotIndex OldIdx) {
+    SlotIndex LastUse = NewIdx;
+    for (MachineRegisterInfo::use_nodbg_iterator
+           UI = MRI.use_nodbg_begin(Reg),
+           UE = MRI.use_nodbg_end();
+         UI != UE; ++UI) {
+      const MachineInstr* MI = &*UI;
+      SlotIndex InstSlot = LIS.getSlotIndexes()->getInstructionIndex(MI);
+      if (InstSlot > LastUse && InstSlot < OldIdx)
+        LastUse = InstSlot;
+    }
+    return LastUse;
+  }
+
+  void moveEnteringUpFrom(SlotIndex OldIdx, IntRangePair& P) {
+    LiveInterval* LI = P.first;
+    LiveRange* LR = P.second;
+    bool LiveThrough = LR->end > OldIdx.getRegSlot();
+    if (LiveThrough)
+      return;
+    SlotIndex LastUse = findLastUseBefore(LI->reg, OldIdx);
+    if (LastUse != NewIdx)
+      moveKillFlags(LI->reg, NewIdx, LastUse);
+    LR->end = LastUse.getRegSlot(LR->end.isEarlyClobber());
+  }
+
+  void moveEnteringDownFrom(SlotIndex OldIdx, IntRangePair& P) {
+    LiveInterval* LI = P.first;
+    LiveRange* LR = P.second;
+    bool LiveThrough = LR->end > OldIdx.getRegSlot();
+    if (LiveThrough) {
+      MachineBasicBlock* MBB = LIS.getInstructionFromIndex(NewIdx)->getParent();
+      bool LiveOut = LR->end >= LIS.getSlotIndexes()->getMBBEndIdx(MBB);
+      if (!LiveOut) {
+        moveKillFlags(LI->reg, LR->end, NewIdx);
+        LR->end = NewIdx.getRegSlot(LR->end.isEarlyClobber());
+      }
+    } else {
+      // Not live through. Easy - just update the range endpoint.
+      LR->end = NewIdx.getRegSlot(LR->end.isEarlyClobber());
+    }
+  }
+
+  void moveAllEnteringFrom(SlotIndex OldIdx, RangeSet& Entering) {
+    bool GoingUp = NewIdx < OldIdx;
+
+    if (GoingUp) {
+      for (RangeSet::iterator EI = Entering.begin(), EE = Entering.end();
+           EI != EE; ++EI)
+        moveEnteringUpFrom(OldIdx, *EI);
+    } else {
+      for (RangeSet::iterator EI = Entering.begin(), EE = Entering.end();
+           EI != EE; ++EI)
+        moveEnteringDownFrom(OldIdx, *EI);
+    }
+  }
+
+  void moveInternalFrom(SlotIndex OldIdx, IntRangePair& P) {
+    LiveInterval* LI = P.first;
+    LiveRange* LR = P.second;
+    assert(OldIdx < LR->start && LR->start < OldIdx.getDeadSlot() &&
+           LR->end <= OldIdx.getDeadSlot() &&
+           "Range should be internal to OldIdx.");
+    LiveRange Tmp(*LR);
+    Tmp.start = NewIdx.getRegSlot(LR->start.isEarlyClobber());
+    Tmp.valno->def = Tmp.start;
+    Tmp.end = LR->end.isDead() ? NewIdx.getDeadSlot() : NewIdx.getRegSlot();
+    LI->removeRange(*LR);
+    LI->addRange(Tmp);
+  }
+
+  void moveAllInternalFrom(SlotIndex OldIdx, RangeSet& Internal) {
+    for (RangeSet::iterator II = Internal.begin(), IE = Internal.end();
+         II != IE; ++II)
+      moveInternalFrom(OldIdx, *II);
+  }
+
+  void moveExitingFrom(SlotIndex OldIdx, IntRangePair& P) {
+    LiveRange* LR = P.second;
+    assert(OldIdx < LR->start && LR->start < OldIdx.getDeadSlot() &&
+           "Range should start in OldIdx.");
+    assert(LR->end > OldIdx.getDeadSlot() && "Range should exit OldIdx.");
+    SlotIndex NewStart = NewIdx.getRegSlot(LR->start.isEarlyClobber());
+    LR->start = NewStart;
+    LR->valno->def = NewStart;
+  }
+
+  void moveAllExitingFrom(SlotIndex OldIdx, RangeSet& Exiting) {
+    for (RangeSet::iterator EI = Exiting.begin(), EE = Exiting.end();
+         EI != EE; ++EI)
+      moveExitingFrom(OldIdx, *EI);
+  }
+
 };
 
 void LiveIntervals::handleMove(MachineInstr* MI) {





More information about the llvm-commits mailing list