[llvm-commits] [llvm] r74518 - in /llvm/trunk: include/llvm/CodeGen/MachineInstrBuilder.h include/llvm/CodeGen/MachineOperand.h include/llvm/CodeGen/RegisterScavenging.h lib/CodeGen/LiveIntervalAnalysis.cpp lib/CodeGen/MachineInstr.cpp lib/CodeGen/RegAllocLinearScan.cpp lib/CodeGen/RegisterScavenging.cpp lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp lib/CodeGen/VirtRegRewriter.cpp lib/Target/X86/X86InstrInfo.cpp test/CodeGen/ARM/2009-06-30-RegScavengerAssert.ll

Evan Cheng evan.cheng at apple.com
Tue Jun 30 01:49:10 PDT 2009


Author: evancheng
Date: Tue Jun 30 03:49:04 2009
New Revision: 74518

URL: http://llvm.org/viewvc/llvm-project?rev=74518&view=rev
Log:
Add a bit IsUndef to MachineOperand. This indicates the def / use register operand is defined by an implicit_def. That means it can def / use any register and passes (e.g. register scavenger) can feel free to ignore them.

The register allocator, when it allocates a register to a virtual register defined by an implicit_def, can allocate any physical register without worrying about overlapping live ranges. It should mark all of operands of the said virtual register so later passes will do the right thing.

This is not the best solution. But it should be a lot less fragile to having the scavenger try to track what is defined by implicit_def.

Added:
    llvm/trunk/test/CodeGen/ARM/2009-06-30-RegScavengerAssert.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h
    llvm/trunk/include/llvm/CodeGen/MachineOperand.h
    llvm/trunk/include/llvm/CodeGen/RegisterScavenging.h
    llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp
    llvm/trunk/lib/CodeGen/MachineInstr.cpp
    llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp
    llvm/trunk/lib/CodeGen/RegisterScavenging.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
    llvm/trunk/lib/CodeGen/VirtRegRewriter.cpp
    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp

Modified: llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineInstrBuilder.h Tue Jun 30 03:49:04 2009
@@ -29,7 +29,8 @@
     Implicit       = 0x4,
     Kill           = 0x8,
     Dead           = 0x10,
-    EarlyClobber   = 0x20,
+    Undef          = 0x20,
+    EarlyClobber   = 0x40,
     ImplicitDefine = Implicit | Define,
     ImplicitKill   = Implicit | Kill
   };
@@ -57,8 +58,9 @@
                                              flags & RegState::Implicit,
                                              flags & RegState::Kill,
                                              flags & RegState::Dead,
-                                             SubReg,
-                                             flags & RegState::EarlyClobber));
+                                             flags & RegState::Undef,
+                                             flags & RegState::EarlyClobber,
+                                             SubReg));
     return *this;
   }
 
@@ -203,6 +205,9 @@
 inline unsigned getDeadRegState(bool B) {
   return B ? RegState::Dead : 0;
 }
+inline unsigned getUndefRegState(bool B) {
+  return B ? RegState::Undef : 0;
+}
 
 } // End llvm namespace
 

Modified: llvm/trunk/include/llvm/CodeGen/MachineOperand.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineOperand.h?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineOperand.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineOperand.h Tue Jun 30 03:49:04 2009
@@ -75,6 +75,10 @@
   /// This is only valid on definitions of registers.
   bool IsDead : 1;
 
+  /// IsUndef - True if this is a register def / use of "undef", i.e. register
+  /// defined by an IMPLICIT_DEF. This is only valid on registers.
+  bool IsUndef : 1;
+
   /// IsEarlyClobber - True if this MO_Register 'def' operand is written to
   /// by the MachineInstr before all input registers are read.  This is used to
   /// model the GCC inline asm '&' constraint modifier.
@@ -198,6 +202,11 @@
     return IsKill;
   }
   
+  bool isUndef() const {
+    assert(isReg() && "Wrong MachineOperand accessor");
+    return IsUndef;
+  }
+  
   bool isEarlyClobber() const {
     assert(isReg() && "Wrong MachineOperand accessor");
     return IsEarlyClobber;
@@ -248,6 +257,11 @@
     IsDead = Val;
   }
 
+  void setIsUndef(bool Val = true) {
+    assert(isReg() && "Wrong MachineOperand accessor");
+    IsUndef = Val;
+  }
+  
   void setIsEarlyClobber(bool Val = true) {
     assert(isReg() && IsDef && "Wrong MachineOperand accessor");
     IsEarlyClobber = Val;
@@ -337,7 +351,8 @@
   /// the specified value.  If an operand is known to be an register already,
   /// the setReg method should be used.
   void ChangeToRegister(unsigned Reg, bool isDef, bool isImp = false,
-                        bool isKill = false, bool isDead = false);
+                        bool isKill = false, bool isDead = false,
+                        bool isUndef = false);
   
   //===--------------------------------------------------------------------===//
   // Construction methods.
@@ -357,13 +372,15 @@
   
   static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp = false,
                                   bool isKill = false, bool isDead = false,
-                                  unsigned SubReg = 0,
-                                  bool isEarlyClobber = false) {
+                                  bool isUndef = false,
+                                  bool isEarlyClobber = false,
+                                  unsigned SubReg = 0) {
     MachineOperand Op(MachineOperand::MO_Register);
     Op.IsDef = isDef;
     Op.IsImp = isImp;
     Op.IsKill = isKill;
     Op.IsDead = isDead;
+    Op.IsUndef = isUndef;
     Op.IsEarlyClobber = isEarlyClobber;
     Op.Contents.Reg.RegNo = Reg;
     Op.Contents.Reg.Prev = 0;
@@ -420,6 +437,7 @@
     IsImp    = MO.IsImp;
     IsKill   = MO.IsKill;
     IsDead   = MO.IsDead;
+    IsUndef  = MO.IsUndef;
     IsEarlyClobber = MO.IsEarlyClobber;
     SubReg   = MO.SubReg;
     ParentMI = MO.ParentMI;

Modified: llvm/trunk/include/llvm/CodeGen/RegisterScavenging.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/RegisterScavenging.h?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/RegisterScavenging.h (original)
+++ llvm/trunk/include/llvm/CodeGen/RegisterScavenging.h Tue Jun 30 03:49:04 2009
@@ -69,10 +69,6 @@
   /// available, unset means the register is currently being used.
   BitVector RegsAvailable;
 
-  /// ImplicitDefed - If bit is set that means the register is defined by an
-  /// implicit_def instructions. That means it can be clobbered at will.
-  BitVector ImplicitDefed;
-
   /// CurrDist - Distance from MBB entry to the current instruction MBBI.
   ///
   unsigned CurrDist;
@@ -117,25 +113,18 @@
   bool isUsed(unsigned Reg) const   { return !RegsAvailable[Reg]; }
   bool isUnused(unsigned Reg) const { return RegsAvailable[Reg]; }
 
-  bool isImplicitlyDefined(unsigned Reg) const { return ImplicitDefed[Reg]; }
-
   /// getRegsUsed - return all registers currently in use in used.
   void getRegsUsed(BitVector &used, bool includeReserved);
 
   /// setUsed / setUnused - Mark the state of one or a number of registers.
   ///
-  void setUsed(unsigned Reg, bool ImpDef = false);
-  void setUsed(BitVector &Regs, bool ImpDef = false) {
+  void setUsed(unsigned Reg);
+  void setUsed(BitVector &Regs) {
     RegsAvailable &= ~Regs;
-    if (ImpDef)
-      ImplicitDefed |= Regs;
-    else
-      ImplicitDefed &= ~Regs;
   }
   void setUnused(unsigned Reg, const MachineInstr *MI);
   void setUnused(BitVector &Regs) {
     RegsAvailable |= Regs;
-    ImplicitDefed &= ~Regs;
   }
 
   /// FindUnusedReg - Find a unused register of the specified register class

Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Tue Jun 30 03:49:04 2009
@@ -1782,8 +1782,12 @@
       NewLIs.push_back(&getOrCreateInterval(NewVReg));
       for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
         MachineOperand &MO = MI->getOperand(i);
-        if (MO.isReg() && MO.getReg() == li.reg)
+        if (MO.isReg() && MO.getReg() == li.reg) {
           MO.setReg(NewVReg);
+          MO.setIsUndef();
+          if (MO.isKill())
+            MO.setIsKill(false);
+        }
       }
     }
   }

Modified: llvm/trunk/lib/CodeGen/MachineInstr.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineInstr.cpp?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/MachineInstr.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineInstr.cpp Tue Jun 30 03:49:04 2009
@@ -120,7 +120,7 @@
 /// the specified value.  If an operand is known to be an register already,
 /// the setReg method should be used.
 void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp,
-                                      bool isKill, bool isDead) {
+                                      bool isKill, bool isDead, bool isUndef) {
   // If this operand is already a register operand, use setReg to update the 
   // register's use/def lists.
   if (isReg()) {
@@ -143,6 +143,7 @@
   IsImp = isImp;
   IsKill = isKill;
   IsDead = isDead;
+  IsUndef = isUndef;
   IsEarlyClobber = false;
   SubReg = 0;
 }
@@ -206,11 +207,11 @@
         OS << "%mreg" << getReg();
     }
 
-    if (getSubReg() != 0) {
+    if (getSubReg() != 0)
       OS << ':' << getSubReg();
-    }
 
-    if (isDef() || isKill() || isDead() || isImplicit() || isEarlyClobber()) {
+    if (isDef() || isKill() || isDead() || isImplicit() || isUndef() ||
+        isEarlyClobber()) {
       OS << '<';
       bool NeedComma = false;
       if (isImplicit()) {
@@ -224,10 +225,15 @@
         OS << "def";
         NeedComma = true;
       }
-      if (isKill() || isDead()) {
+      if (isKill() || isDead() || isUndef()) {
         if (NeedComma) OS << ',';
         if (isKill())  OS << "kill";
         if (isDead())  OS << "dead";
+        if (isUndef()) {
+          if (isKill() || isDead())
+            OS << ',';
+          OS << "undef";
+        }
       }
       OS << '>';
     }

Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Tue Jun 30 03:49:04 2009
@@ -905,6 +905,17 @@
     DOUT <<  tri_->getName(physReg) << '\n';
     // Note the register is not really in use.
     vrm_->assignVirt2Phys(cur->reg, physReg);
+    // Since the register allocator is allowed to assign this virtual register
+    // physical register that overlaps other live intervals. Mark these
+    // operands as "Undef" which means later passes, e.g. register scavenger
+    // can ignore them.
+    for (MachineRegisterInfo::reg_iterator RI = mri_->reg_begin(cur->reg),
+           RE = mri_->reg_end(); RI != RE; ++RI) {
+      MachineOperand &MO = RI.getOperand();
+      MO.setIsUndef();
+      if (MO.isKill())
+        MO.setIsKill(false);
+    }
     return;
   }
 

Modified: llvm/trunk/lib/CodeGen/RegisterScavenging.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterScavenging.cpp?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/RegisterScavenging.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegisterScavenging.cpp Tue Jun 30 03:49:04 2009
@@ -36,7 +36,7 @@
   bool SeenSuperDef = false;
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = MI->getOperand(i);
-    if (!MO.isReg())
+    if (!MO.isReg() || MO.isUndef())
       continue;
     if (TRI->isSuperRegister(SubReg, MO.getReg())) {
       if (MO.isUse())
@@ -57,28 +57,22 @@
 }
 
 /// setUsed - Set the register and its sub-registers as being used.
-void RegScavenger::setUsed(unsigned Reg, bool ImpDef) {
+void RegScavenger::setUsed(unsigned Reg) {
   RegsAvailable.reset(Reg);
-  ImplicitDefed[Reg] = ImpDef;
 
   for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
-       unsigned SubReg = *SubRegs; ++SubRegs) {
+       unsigned SubReg = *SubRegs; ++SubRegs)
     RegsAvailable.reset(SubReg);
-    ImplicitDefed[SubReg] = ImpDef;
-  }
 }
 
 /// setUnused - Set the register and its sub-registers as being unused.
 void RegScavenger::setUnused(unsigned Reg, const MachineInstr *MI) {
   RegsAvailable.set(Reg);
-  ImplicitDefed.reset(Reg);
 
   for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
        unsigned SubReg = *SubRegs; ++SubRegs)
-    if (!RedefinesSuperRegPart(MI, Reg, TRI)) {
+    if (!RedefinesSuperRegPart(MI, Reg, TRI))
       RegsAvailable.set(SubReg);
-      ImplicitDefed.reset(SubReg);
-    }
 }
 
 void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
@@ -94,7 +88,6 @@
   if (!MBB) {
     NumPhysRegs = TRI->getNumRegs();
     RegsAvailable.resize(NumPhysRegs);
-    ImplicitDefed.resize(NumPhysRegs);
 
     // Create reserved registers bitvector.
     ReservedRegs = TRI->getReservedRegs(MF);
@@ -113,7 +106,6 @@
   ScavengeRestore = NULL;
   CurrDist = 0;
   DistanceMap.clear();
-  ImplicitDefed.reset();
 
   // All registers started out unused.
   RegsAvailable.set();
@@ -195,15 +187,13 @@
     ScavengeRestore = NULL;
   }
 
-  bool IsImpDef = MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF;
-
   // Separate register operands into 3 classes: uses, defs, earlyclobbers.
   SmallVector<std::pair<const MachineOperand*,unsigned>, 4> UseMOs;
   SmallVector<std::pair<const MachineOperand*,unsigned>, 4> DefMOs;
   SmallVector<std::pair<const MachineOperand*,unsigned>, 4> EarlyClobberMOs;
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = MI->getOperand(i);
-    if (!MO.isReg() || MO.getReg() == 0)
+    if (!MO.isReg() || MO.getReg() == 0 || MO.isUndef())
       continue;
     if (MO.isUse())
       UseMOs.push_back(std::make_pair(&MO,i));
@@ -221,14 +211,7 @@
 
     assert(isUsed(Reg) && "Using an undefined register!");
 
-    // Kill of implicit_def defined registers are ignored. e.g.
-    // entry: 0x2029ab8, LLVM BB @0x1b06080, ID#0:
-    // Live Ins: %R0
-    //  %R0<def> = IMPLICIT_DEF
-    //  %R0<def> = IMPLICIT_DEF
-    //  STR %R0<kill>, %R0, %reg0, 0, 14, %reg0, Mem:ST(4,4) [0x1b06510 + 0]
-    //  %R1<def> = LDR %R0, %reg0, 24, 14, %reg0, Mem:LD(4,4) [0x1b065bc + 0]
-    if (MO.isKill() && !isReserved(Reg) && !isImplicitlyDefined(Reg)) {
+    if (MO.isKill() && !isReserved(Reg)) {
       KillRegs.set(Reg);
 
       // Mark sub-registers as used.
@@ -274,10 +257,9 @@
     // Implicit def is allowed to "re-define" any register. Similarly,
     // implicitly defined registers can be clobbered.
     assert((isReserved(Reg) || isUnused(Reg) ||
-            IsImpDef || isImplicitlyDefined(Reg) ||
             isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) &&
            "Re-defining a live register!");
-    setUsed(Reg, IsImpDef);
+    setUsed(Reg);
   }
 }
 
@@ -297,7 +279,7 @@
   SmallVector<std::pair<const MachineOperand*,unsigned>, 4> EarlyClobberMOs;
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = MI->getOperand(i);
-    if (!MO.isReg() || MO.getReg() == 0)
+    if (!MO.isReg() || MO.getReg() == 0 || MO.isUndef())
       continue;
     if (MO.isUse())
       UseMOs.push_back(std::make_pair(&MO,i));

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp Tue Jun 30 03:49:04 2009
@@ -617,7 +617,7 @@
         for (; NumVals; --NumVals, ++i) {
           unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
           MI->addOperand(MachineOperand::CreateReg(Reg, true, false, false, 
-                                                   false, 0, true));
+                                                   false, false, true));
         }
         break;
       case 1:  // Use of register.

Modified: llvm/trunk/lib/CodeGen/VirtRegRewriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/VirtRegRewriter.cpp?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/VirtRegRewriter.cpp (original)
+++ llvm/trunk/lib/CodeGen/VirtRegRewriter.cpp Tue Jun 30 03:49:04 2009
@@ -356,7 +356,7 @@
                             SmallVector<unsigned, 2> *KillRegs = NULL) {
   for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
     MachineOperand &MO = MI.getOperand(i);
-    if (!MO.isReg() || !MO.isUse() || !MO.isKill())
+    if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef())
       continue;
     unsigned Reg = MO.getReg();
     if (TargetRegisterInfo::isVirtualRegister(Reg))
@@ -390,12 +390,12 @@
   MachineOperand *DefOp = NULL;
   for (unsigned i = 0, e = DefMI->getNumOperands(); i != e; ++i) {
     MachineOperand &MO = DefMI->getOperand(i);
-    if (MO.isReg() && MO.isDef()) {
-      if (MO.getReg() == Reg)
-        DefOp = &MO;
-      else if (!MO.isDead())
-        HasLiveDef = true;
-    }
+    if (!MO.isReg() || !MO.isUse() || !MO.isKill() || MO.isUndef())
+      continue;
+    if (MO.getReg() == Reg)
+      DefOp = &MO;
+    else if (!MO.isDead())
+      HasLiveDef = true;
   }
   if (!DefOp)
     return false;
@@ -430,7 +430,7 @@
                         std::vector<MachineOperand*> &KillOps) {
   for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
     MachineOperand &MO = MI.getOperand(i);
-    if (!MO.isReg() || !MO.isUse())
+    if (!MO.isReg() || !MO.isUse() || MO.isUndef())
       continue;
     unsigned Reg = MO.getReg();
     if (Reg == 0)
@@ -1289,8 +1289,7 @@
           if (InvalidateRegDef(PrevMII, *MII, KillRegs[j], HasOtherDef)) {
             MachineInstr *DeadDef = PrevMII;
             if (ReMatDefs.count(DeadDef) && !HasOtherDef) {
-              // FIXME: This assumes a remat def does not have side
-              // effects.
+              // FIXME: This assumes a remat def does not have side effects.
               VRM.RemoveMachineInstrFromMaps(DeadDef);
               MBB.erase(DeadDef);
               ++NumDRM;
@@ -1569,6 +1568,8 @@
         if (MO.isImplicit())
           // If the virtual register is implicitly defined, emit a implicit_def
           // before so scavenger knows it's "defined".
+          // FIXME: This is a horrible hack done the by register allocator to
+          // remat a definition with virtual register operand.
           VirtUseOps.insert(VirtUseOps.begin(), i);
         else
           VirtUseOps.push_back(i);
@@ -1595,6 +1596,7 @@
           MI.getOperand(i).setReg(RReg);
           MI.getOperand(i).setSubReg(0);
           if (VRM.isImplicitlyDefined(VirtReg))
+            // FIXME: Is this needed?
             BuildMI(MBB, &MI, MI.getDebugLoc(),
                     TII->get(TargetInstrInfo::IMPLICIT_DEF), RReg);
           continue;
@@ -1604,22 +1606,16 @@
         if (!MO.isUse())
           continue;  // Handle defs in the loop below (handle use&def here though)
 
-        bool AvoidReload = false;
-        if (LIs->hasInterval(VirtReg)) {
-          LiveInterval &LI = LIs->getInterval(VirtReg);
-          if (!LI.liveAt(LIs->getUseIndex(LI.beginNumber())))
-            // Must be defined by an implicit def. It should not be spilled. Note,
-            // this is for correctness reason. e.g.
-            // 8   %reg1024<def> = IMPLICIT_DEF
-            // 12  %reg1024<def> = INSERT_SUBREG %reg1024<kill>, %reg1025, 2
-            // The live range [12, 14) are not part of the r1024 live interval since
-            // it's defined by an implicit def. It will not conflicts with live
-            // interval of r1025. Now suppose both registers are spilled, you can
-            // easily see a situation where both registers are reloaded before
-            // the INSERT_SUBREG and both target registers that would overlap.
-            AvoidReload = true;
-        }
-
+        bool AvoidReload = MO.isUndef();
+        // Check if it is defined by an implicit def. It should not be spilled.
+        // Note, this is for correctness reason. e.g.
+        // 8   %reg1024<def> = IMPLICIT_DEF
+        // 12  %reg1024<def> = INSERT_SUBREG %reg1024<kill>, %reg1025, 2
+        // The live range [12, 14) are not part of the r1024 live interval since
+        // it's defined by an implicit def. It will not conflicts with live
+        // interval of r1025. Now suppose both registers are spilled, you can
+        // easily see a situation where both registers are reloaded before
+        // the INSERT_SUBREG and both target registers that would overlap.
         bool DoReMat = VRM.isReMaterialized(VirtReg);
         int SSorRMId = DoReMat
           ? VRM.getReMatId(VirtReg) : VRM.getStackSlot(VirtReg);

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=74518&r1=74517&r2=74518&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Jun 30 03:49:04 2009
@@ -2459,7 +2459,8 @@
                getDefRegState(MO.isDef()) |
                RegState::Implicit |
                getKillRegState(MO.isKill()) |
-               getDeadRegState(MO.isDead()));
+               getDeadRegState(MO.isDead()) |
+               getUndefRegState(MO.isUndef()));
   }
   // Change CMP32ri r, 0 back to TEST32rr r, r, etc.
   unsigned NewOpc = 0;

Added: llvm/trunk/test/CodeGen/ARM/2009-06-30-RegScavengerAssert.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2009-06-30-RegScavengerAssert.ll?rev=74518&view=auto

==============================================================================
--- llvm/trunk/test/CodeGen/ARM/2009-06-30-RegScavengerAssert.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/2009-06-30-RegScavengerAssert.ll Tue Jun 30 03:49:04 2009
@@ -0,0 +1,122 @@
+; RUN: llvm-as < %s | llc -march=arm -mtriple=armv6-apple-darwin9
+
+ at nn = external global i32		; <i32*> [#uses=1]
+ at al_len = external global i32		; <i32*> [#uses=2]
+ at no_mat = external global i32		; <i32*> [#uses=2]
+ at no_mis = external global i32		; <i32*> [#uses=2]
+@"\01LC12" = external constant [29 x i8], align 1		; <[29 x i8]*> [#uses=1]
+@"\01LC16" = external constant [33 x i8], align 1		; <[33 x i8]*> [#uses=1]
+@"\01LC17" = external constant [47 x i8], align 1		; <[47 x i8]*> [#uses=1]
+
+declare arm_apcscc i32 @printf(i8* nocapture, ...) nounwind
+
+declare arm_apcscc void @diff(i8*, i8*, i32, i32, i32, i32) nounwind
+
+define arm_apcscc void @SIM(i8* %A, i8* %B, i32 %M, i32 %N, i32 %K, [256 x i32]* %V, i32 %Q, i32 %R, i32 %nseq) nounwind {
+entry:
+	br i1 undef, label %bb5, label %bb
+
+bb:		; preds = %bb, %entry
+	br label %bb
+
+bb5:		; preds = %entry
+	br i1 undef, label %bb6, label %bb8
+
+bb6:		; preds = %bb6, %bb5
+	br i1 undef, label %bb8, label %bb6
+
+bb8:		; preds = %bb6, %bb5
+	br label %bb15
+
+bb9:		; preds = %bb15
+	br i1 undef, label %bb10, label %bb11
+
+bb10:		; preds = %bb9
+	unreachable
+
+bb11:		; preds = %bb9
+	%0 = load i32* undef, align 4		; <i32> [#uses=2]
+	%1 = add i32 %0, 1		; <i32> [#uses=2]
+	store i32 %1, i32* undef, align 4
+	%2 = load i32* undef, align 4		; <i32> [#uses=1]
+	store i32 %2, i32* @nn, align 4
+	store i32 0, i32* @al_len, align 4
+	store i32 0, i32* @no_mat, align 4
+	store i32 0, i32* @no_mis, align 4
+	%3 = getelementptr i8* %B, i32 %0		; <i8*> [#uses=1]
+	tail call arm_apcscc  void @diff(i8* undef, i8* %3, i32 undef, i32 undef, i32 undef, i32 undef) nounwind
+	%4 = sitofp i32 undef to double		; <double> [#uses=1]
+	%5 = fdiv double %4, 1.000000e+01		; <double> [#uses=1]
+	%6 = tail call arm_apcscc  i32 (i8*, ...)* @printf(i8* getelementptr ([29 x i8]* @"\01LC12", i32 0, i32 0), double %5) nounwind		; <i32> [#uses=0]
+	%7 = load i32* @al_len, align 4		; <i32> [#uses=1]
+	%8 = load i32* @no_mat, align 4		; <i32> [#uses=1]
+	%9 = load i32* @no_mis, align 4		; <i32> [#uses=1]
+	%10 = sub i32 %7, %8		; <i32> [#uses=1]
+	%11 = sub i32 %10, %9		; <i32> [#uses=1]
+	%12 = tail call arm_apcscc  i32 (i8*, ...)* @printf(i8* getelementptr ([33 x i8]* @"\01LC16", i32 0, i32 0), i32 %11) nounwind		; <i32> [#uses=0]
+	%13 = tail call arm_apcscc  i32 (i8*, ...)* @printf(i8* getelementptr ([47 x i8]* @"\01LC17", i32 0, i32 0), i32 undef, i32 %1, i32 undef, i32 undef) nounwind		; <i32> [#uses=0]
+	br i1 undef, label %bb15, label %bb12
+
+bb12:		; preds = %bb11
+	br label %bb228.i
+
+bb74.i:		; preds = %bb228.i
+	br i1 undef, label %bb138.i, label %bb145.i
+
+bb138.i:		; preds = %bb74.i
+	br label %bb145.i
+
+bb145.i:		; preds = %bb228.i, %bb138.i, %bb74.i
+	br i1 undef, label %bb146.i, label %bb151.i
+
+bb146.i:		; preds = %bb145.i
+	br i1 undef, label %bb228.i, label %bb151.i
+
+bb151.i:		; preds = %bb146.i, %bb145.i
+	br i1 undef, label %bb153.i, label %bb228.i
+
+bb153.i:		; preds = %bb151.i
+	br i1 undef, label %bb220.i, label %bb.nph.i98
+
+bb.nph.i98:		; preds = %bb153.i
+	br label %bb158.i
+
+bb158.i:		; preds = %bb218.i, %bb.nph.i98
+	br i1 undef, label %bb168.i, label %bb160.i
+
+bb160.i:		; preds = %bb158.i
+	br i1 undef, label %bb161.i, label %bb168.i
+
+bb161.i:		; preds = %bb160.i
+	br i1 undef, label %bb168.i, label %bb163.i
+
+bb163.i:		; preds = %bb161.i
+	br i1 undef, label %bb167.i, label %bb168.i
+
+bb167.i:		; preds = %bb163.i
+	br label %bb168.i
+
+bb168.i:		; preds = %bb167.i, %bb163.i, %bb161.i, %bb160.i, %bb158.i
+	br i1 undef, label %bb211.i, label %bb218.i
+
+bb211.i:		; preds = %bb168.i
+	br label %bb218.i
+
+bb218.i:		; preds = %bb211.i, %bb168.i
+	br i1 undef, label %bb220.i, label %bb158.i
+
+bb220.i:		; preds = %bb218.i, %bb153.i
+	br i1 undef, label %bb221.i, label %bb228.i
+
+bb221.i:		; preds = %bb220.i
+	br label %bb228.i
+
+bb228.i:		; preds = %bb221.i, %bb220.i, %bb151.i, %bb146.i, %bb12
+	br i1 undef, label %bb74.i, label %bb145.i
+
+bb15:		; preds = %bb11, %bb8
+	br i1 undef, label %return, label %bb9
+
+return:		; preds = %bb15
+	ret void
+}





More information about the llvm-commits mailing list