Add support for updating the LiveIntervals of registers used by 'exotic'
authorCameron Zwarich <zwarich@apple.com>
Sun, 17 Feb 2013 00:10:44 +0000 (00:10 +0000)
committerCameron Zwarich <zwarich@apple.com>
Sun, 17 Feb 2013 00:10:44 +0000 (00:10 +0000)
terminators that actually have register uses when splitting critical edges.

This commit also introduces a method repairIntervalsInRange() on LiveIntervals,
which allows for repairing LiveIntervals in a small range after an arbitrary
target hook modifies, inserts, and removes instructions. It's pretty limited
right now, but I hope to extend it to support all of the things that are done
by the convertToThreeAddress() target hooks.

llvm-svn: 175382

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

index b6cc111..f422a6f 100644 (file)
@@ -281,6 +281,21 @@ namespace llvm {
     void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart,
                               bool UpdateFlags = false);
 
+    /// repairIntervalsInRange - Update live intervals for instructions in a
+    /// small range of reverse iterators. It is intended for use after target
+    /// hooks that may insert or remove instructions, and is only efficient for
+    /// a small number of instructions.
+    ///
+    /// OrigRegs is a vector of registers that were originally used by the
+    /// instructions in the range between the two iterators.
+    ///
+    /// Currently, the only only changes that are supported are simple removal
+    /// and addition of uses.
+    void repairIntervalsInRange(MachineBasicBlock *MBB,
+                                MachineBasicBlock::reverse_iterator RBegin,
+                                MachineBasicBlock::reverse_iterator REnd,
+                                SmallVectorImpl<unsigned> &OrigRegs);
+
     // Register mask functions.
     //
     // Machine instructions may use a register mask operand to indicate that a
index 0d4ec11..3c67be5 100644 (file)
@@ -1032,3 +1032,39 @@ void LiveIntervals::handleMoveIntoBundle(MachineInstr* MI,
   HMEditor HME(*this, *MRI, *TRI, OldIndex, NewIndex, UpdateFlags);
   HME.updateAllRanges(MI);
 }
+
+void
+LiveIntervals::repairIntervalsInRange(MachineBasicBlock *MBB,
+                                     MachineBasicBlock::reverse_iterator RBegin,
+                                     MachineBasicBlock::reverse_iterator REnd,
+                                     SmallVectorImpl<unsigned> &OrigRegs) {
+  for (unsigned i = 0, e = OrigRegs.size(); i != e; ++i) {
+    unsigned Reg = OrigRegs[i];
+    if (!TargetRegisterInfo::isVirtualRegister(Reg))
+      continue;
+
+    LiveInterval &LI = getInterval(Reg);
+    SlotIndex startIdx = (REnd == MBB->rend()) ? getMBBStartIdx(MBB)
+                                               : getInstructionIndex(&*REnd);
+    for (MachineBasicBlock::reverse_iterator I = RBegin; I != REnd; ++I) {
+      MachineInstr *MI = &*I;
+      SlotIndex instrIdx = getInstructionIndex(MI);
+
+      for (MachineInstr::mop_iterator OI = MI->operands_begin(),
+           OE = MI->operands_end(); OI != OE; ++OI) {
+        const MachineOperand &MO = *OI;
+        if (!MO.isReg() || MO.getReg() != Reg)
+          continue;
+
+        assert(MO.isUse() && "Register defs are not yet supported.");
+
+        if (!LI.liveAt(instrIdx)) {
+          LiveRange *LR = LI.getLiveRangeContaining(startIdx.getRegSlot());
+          assert(LR && "Used registers must be live-in.");
+          LR->end = instrIdx.getRegSlot();
+          break;
+        }
+      }
+    }
+  }
+}
index df1c7c2..3d75436 100644 (file)
@@ -698,6 +698,24 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) {
       }
     }
 
+  SmallVector<unsigned, 4> UsedRegs;
+  if (LIS) {
+    for (instr_iterator I = getFirstInstrTerminator(), E = instr_end();
+         I != E; ++I) {
+      MachineInstr *MI = I;
+
+      for (MachineInstr::mop_iterator OI = MI->operands_begin(),
+           OE = MI->operands_end(); OI != OE; ++OI) {
+        if (!OI->isReg() || OI->getReg() == 0)
+          continue;
+
+        unsigned Reg = OI->getReg();
+        if (std::find(UsedRegs.begin(), UsedRegs.end(), Reg) == UsedRegs.end())
+          UsedRegs.push_back(Reg);
+      }
+    }
+  }
+
   ReplaceUsesOfBlockWith(Succ, NMBB);
 
   // If updateTerminator() removes instructions, we need to remove them from
@@ -830,6 +848,17 @@ MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) {
         LI.removeRange(StartIndex, EndIndex);
       }
     }
+
+    // Update all intervals for registers whose uses may have been modified by
+    // updateTerminator().
+    iterator FirstTerminator = getFirstTerminator();
+    MachineInstr *FirstTerminatorMI = FirstTerminator;
+    if (FirstTerminatorMI->isBundled())
+      FirstTerminatorMI = getBundleStart(FirstTerminatorMI);
+    reverse_iterator PreTerminators =
+      (FirstTerminator == begin()) ? rend()
+                                   : reverse_iterator(FirstTerminatorMI);
+    LIS->repairIntervalsInRange(this, rbegin(), PreTerminators, UsedRegs);
   }
 
   if (MachineDominatorTree *MDT =