[llvm-commits] CVS: llvm/lib/CodeGen/LiveIntervalAnalysis.cpp LiveIntervalAnalysis.h

Chris Lattner lattner at cs.uiuc.edu
Wed Mar 9 15:05:35 PST 2005



Changes in directory llvm/lib/CodeGen:

LiveIntervalAnalysis.cpp updated: 1.134 -> 1.135
LiveIntervalAnalysis.h updated: 1.44 -> 1.45
---
Log message:

Allow the live interval analysis pass to be a bit more aggressive about
numbering values in live ranges for physical registers.

The alpha backend currently generates code that looks like this:

  vreg = preg
...
  preg = vreg
  use preg
...
  preg = vreg
  use preg

etc.  Because vreg contains the value of preg coming in, each of the 
copies back into preg contain that initial value as well.

In the case of the Alpha, this allows this testcase:

void "foo"(int %blah) {
        store int 5, int *%MyVar
        store int 12, int* %MyVar2
        ret void
}

to compile to:

foo:
        ldgp $29, 0($27)
        ldiq $0,5
        stl $0,MyVar
        ldiq $0,12
        stl $0,MyVar2
        ret $31,($26),1

instead of:

foo:
        ldgp $29, 0($27)
        bis $29,$29,$0
        ldiq $1,5
        bis $0,$0,$29
        stl $1,MyVar
        ldiq $1,12
        bis $0,$0,$29
        stl $1,MyVar2
        ret $31,($26),1

This does not seem to have any noticable effect on X86 code.

This fixes PR535: http://llvm.cs.uiuc.edu/PR535 .



---
Diffs of the changes:  (+62 -10)

 LiveIntervalAnalysis.cpp |   60 +++++++++++++++++++++++++++++++++++++++++------
 LiveIntervalAnalysis.h   |   12 +++++++--
 2 files changed, 62 insertions(+), 10 deletions(-)


Index: llvm/lib/CodeGen/LiveIntervalAnalysis.cpp
diff -u llvm/lib/CodeGen/LiveIntervalAnalysis.cpp:1.134 llvm/lib/CodeGen/LiveIntervalAnalysis.cpp:1.135
--- llvm/lib/CodeGen/LiveIntervalAnalysis.cpp:1.134	Sat Jan  8 13:54:59 2005
+++ llvm/lib/CodeGen/LiveIntervalAnalysis.cpp	Wed Mar  9 17:05:19 2005
@@ -58,6 +58,8 @@
   EnableJoining("join-liveintervals",
                 cl::desc("Join compatible live intervals"),
                 cl::init(true));
+  cl::opt<bool>
+  DisableHack("disable-hack");
 };
 
 void LiveIntervals::getAnalysisUsage(AnalysisUsage &AU) const
@@ -86,6 +88,7 @@
   mf_ = &fn;
   tm_ = &fn.getTarget();
   mri_ = tm_->getRegisterInfo();
+  tii_ = tm_->getInstrInfo();
   lv_ = &getAnalysis<LiveVariables>();
   allocatableRegs_ = mri_->getAllocatableSet(fn);
   r2rMap_.grow(mf_->getSSARegMap()->getLastVirtReg());
@@ -120,7 +123,6 @@
   // perform a final pass over the instructions and compute spill
   // weights, coalesce virtual registers and remove identity moves
   const LoopInfo& loopInfo = getAnalysis<LoopInfo>();
-  const TargetInstrInfo& tii = *tm_->getInstrInfo();
 
   for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end();
        mbbi != mbbe; ++mbbi) {
@@ -131,7 +133,7 @@
          mii != mie; ) {
       // if the move will be an identity move delete it
       unsigned srcReg, dstReg, RegRep;
-      if (tii.isMoveInstr(*mii, srcReg, dstReg) &&
+      if (tii_->isMoveInstr(*mii, srcReg, dstReg) &&
           (RegRep = rep(srcReg)) == rep(dstReg)) {
         // remove from def list
         LiveInterval &interval = getOrCreateInterval(RegRep);
@@ -444,7 +446,8 @@
 
 void LiveIntervals::handlePhysicalRegisterDef(MachineBasicBlock *MBB,
                                               MachineBasicBlock::iterator mi,
-                                              LiveInterval& interval)
+                                              LiveInterval& interval,
+                                              unsigned SrcReg, unsigned DestReg)
 {
   // A physical register cannot be live across basic block, so its
   // lifetime must end somewhere in its defining basic block.
@@ -486,6 +489,45 @@
 
 exit:
   assert(start < end && "did not find end of interval?");
+
+  // Finally, if this is defining a new range for the physical register, and if
+  // that physreg is just a copy from a vreg, and if THAT vreg was a copy from
+  // the physreg, then the new fragment has the same value as the one copied
+  // into the vreg.
+  if (interval.reg == DestReg && !interval.empty() &&
+      MRegisterInfo::isVirtualRegister(SrcReg) && !DisableHack) {
+
+    // Get the live interval for the vreg, see if it is defined by a copy.
+    LiveInterval &SrcInterval = getOrCreateInterval(SrcReg);
+
+    if (SrcInterval.containsOneValue()) {
+      assert(!SrcInterval.empty() && "Can't contain a value and be empty!");
+
+      // Get the first index of the first range.  Though the interval may have
+      // multiple liveranges in it, we only check the first.
+      unsigned StartIdx = SrcInterval.begin()->start;
+      MachineInstr *SrcDefMI = getInstructionFromIndex(StartIdx);
+
+      // Check to see if the vreg was defined by a copy instruction, and that
+      // the source was this physreg.
+      unsigned VRegSrcSrc, VRegSrcDest;
+      if (tii_->isMoveInstr(*SrcDefMI, VRegSrcSrc, VRegSrcDest) &&
+          SrcReg == VRegSrcDest && VRegSrcSrc == DestReg) {
+        // Okay, now we know that the vreg was defined by a copy from this
+        // physreg.  Find the value number being copied and use it as the value
+        // for this range.
+        const LiveRange *DefRange = interval.getLiveRangeContaining(StartIdx-1);
+        if (DefRange) {
+          LiveRange LR(start, end, DefRange->ValId);
+          interval.addRange(LR);
+          DEBUG(std::cerr << " +" << LR << '\n');
+          return;
+        }
+      }
+    }
+  }
+
+
   LiveRange LR(start, end, interval.getNextValue());
   interval.addRange(LR);
   DEBUG(std::cerr << " +" << LR << '\n');
@@ -497,9 +539,14 @@
   if (MRegisterInfo::isVirtualRegister(reg))
     handleVirtualRegisterDef(MBB, MI, getOrCreateInterval(reg));
   else if (allocatableRegs_[reg]) {
-    handlePhysicalRegisterDef(MBB, MI, getOrCreateInterval(reg));
+    unsigned SrcReg = 0, DestReg = 0;
+    bool IsMove = tii_->isMoveInstr(*MI, SrcReg, DestReg);
+
+    handlePhysicalRegisterDef(MBB, MI, getOrCreateInterval(reg),
+                              SrcReg, DestReg);
     for (const unsigned* AS = mri_->getAliasSet(reg); *AS; ++AS)
-      handlePhysicalRegisterDef(MBB, MI, getOrCreateInterval(*AS));
+      handlePhysicalRegisterDef(MBB, MI, getOrCreateInterval(*AS),
+                                SrcReg, DestReg);
   }
 }
 
@@ -541,7 +588,6 @@
 
 void LiveIntervals::joinIntervalsInMachineBB(MachineBasicBlock *MBB) {
   DEBUG(std::cerr << ((Value*)MBB->getBasicBlock())->getName() << ":\n");
-  const TargetInstrInfo &TII = *tm_->getInstrInfo();
 
   for (MachineBasicBlock::iterator mi = MBB->begin(), mie = MBB->end();
        mi != mie; ++mi) {
@@ -551,7 +597,7 @@
     // physical registers since we do not have liveness information
     // on not allocatable physical registers
     unsigned regA, regB;
-    if (TII.isMoveInstr(*mi, regA, regB) &&
+    if (tii_->isMoveInstr(*mi, regA, regB) &&
         (MRegisterInfo::isVirtualRegister(regA) || allocatableRegs_[regA]) &&
         (MRegisterInfo::isVirtualRegister(regB) || allocatableRegs_[regB])) {
 


Index: llvm/lib/CodeGen/LiveIntervalAnalysis.h
diff -u llvm/lib/CodeGen/LiveIntervalAnalysis.h:1.44 llvm/lib/CodeGen/LiveIntervalAnalysis.h:1.45
--- llvm/lib/CodeGen/LiveIntervalAnalysis.h:1.44	Mon Dec  6 22:03:45 2004
+++ llvm/lib/CodeGen/LiveIntervalAnalysis.h	Wed Mar  9 17:05:19 2005
@@ -28,12 +28,14 @@
 
   class LiveVariables;
   class MRegisterInfo;
+  class TargetInstrInfo;
   class VirtRegMap;
 
   class LiveIntervals : public MachineFunctionPass {
     MachineFunction* mf_;
     const TargetMachine* tm_;
     const MRegisterInfo* mri_;
+    const TargetInstrInfo* tii_;
     LiveVariables* lv_;
 
     typedef std::map<MachineInstr*, unsigned> Mi2IndexMap;
@@ -154,11 +156,15 @@
                                   MachineBasicBlock::iterator mi,
                                   LiveInterval& interval);
 
-    /// handlePhysicalRegisterDef - update intervals for a
-    /// physical register def
+    /// handlePhysicalRegisterDef - update intervals for a physical register
+    /// def.  If the defining instruction is a move instruction, SrcReg will be
+    /// the input register, and DestReg will be the result.  Note that Interval
+    /// may not match DestReg (it might be an alias instead).
+    ///
     void handlePhysicalRegisterDef(MachineBasicBlock* mbb,
                                    MachineBasicBlock::iterator mi,
-                                   LiveInterval& interval);
+                                   LiveInterval& interval,
+                                   unsigned SrcReg, unsigned DestReg);
 
     /// Return true if the two specified registers belong to different
     /// register classes.  The registers may be either phys or virt regs.






More information about the llvm-commits mailing list