When setting the "unused" info, take into account something like this:
authorBill Wendling <isanbard@gmail.com>
Thu, 6 Mar 2008 23:22:43 +0000 (23:22 +0000)
committerBill Wendling <isanbard@gmail.com>
Thu, 6 Mar 2008 23:22:43 +0000 (23:22 +0000)
    %r3<def> = OR %x3<kill>, %x3

We don't want to mark the %r3 as unused even though it's a sub-register of %x3.

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

include/llvm/CodeGen/RegisterScavenging.h
lib/CodeGen/RegisterScavenging.cpp

index 63b3289c7f28e55b8168754a5a85c519cb8d8e29..f5a21639fb9f4bb8903f8f6d0d3e3656924232ed 100644 (file)
@@ -98,7 +98,7 @@ public:
   ///
   void setUsed(unsigned Reg);
   void setUsed(BitVector Regs)   { RegsAvailable &= ~Regs; }
-  void setUnused(unsigned Reg);
+  void setUnused(unsigned Reg, const MachineInstr *MI);
   void setUnused(BitVector Regs) { RegsAvailable |= Regs; }
 
   /// FindUnusedReg - Find a unused register of the specified register class
index c074706249b70276c1e16eda783fb251c927be1a..635e0cc825baed924974051d6001d4cf7ee46046 100644 (file)
@@ -8,9 +8,9 @@
 //===----------------------------------------------------------------------===//
 //
 // This file implements the machine register scavenger. It can provide
-// information such as unused register at any point in a machine basic block.
-// It also provides a mechanism to make registers availbale by evicting them
-// to spill slots.
+// information, such as unused registers, at any point in a machine basic block.
+// It also provides a mechanism to make registers available by evicting them to
+// spill slots.
 //
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/STLExtras.h"
 using namespace llvm;
 
+/// RedefinesSuperRegPart - Return true if the specified register is redefining
+/// part of a super-register.
+static bool RedefinesSuperRegPart(const MachineInstr *MI, unsigned SubReg,
+                                  const TargetRegisterInfo *TRI) {
+  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+    const MachineOperand &MO = MI->getOperand(i);
+    if (!MO.isRegister() || !MO.isUse())
+      continue;
+    if (TRI->isSuperRegister(SubReg, MO.getReg()))
+      return true;
+  }
+
+  return false;
+}
+
+static bool RedefinesSuperRegPart(const MachineInstr *MI,
+                                  const MachineOperand &MO,
+                                  const TargetRegisterInfo *TRI) {
+  assert(MO.isRegister() && MO.isDef() && "Not a register def!");
+  return RedefinesSuperRegPart(MI, MO.getReg(), TRI);
+}
+
 /// setUsed - Set the register and its sub-registers as being used.
 void RegScavenger::setUsed(unsigned Reg) {
   RegsAvailable.reset(Reg);
@@ -35,12 +57,13 @@ void RegScavenger::setUsed(unsigned Reg) {
 }
 
 /// setUnused - Set the register and its sub-registers as being unused.
-void RegScavenger::setUnused(unsigned Reg) {
+void RegScavenger::setUnused(unsigned Reg, const MachineInstr *MI) {
   RegsAvailable.set(Reg);
 
   for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
        unsigned SubReg = *SubRegs; ++SubRegs)
-    RegsAvailable.set(SubReg);
+    if (!RedefinesSuperRegPart(MI, Reg, TRI))
+      RegsAvailable.set(SubReg);
 }
 
 void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
@@ -138,9 +161,12 @@ void RegScavenger::forward() {
     if (MO.isKill() && !isReserved(Reg)) {
       ChangedRegs.set(Reg);
 
+      // Mark sub-registers as changed if they aren't defined in the same
+      // instruction.
       for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
            unsigned SubReg = *SubRegs; ++SubRegs)
-        ChangedRegs.set(SubReg);
+        if (!RedefinesSuperRegPart(MI, Reg, TRI))
+          ChangedRegs.set(SubReg);
     }
   }
 
@@ -159,7 +185,7 @@ void RegScavenger::forward() {
 
     // If it's dead upon def, then it is now free.
     if (MO.isDead()) {
-      setUnused(Reg);
+      setUnused(Reg, MI);
       continue;
     }
 
@@ -169,6 +195,10 @@ void RegScavenger::forward() {
       continue;
     }
 
+    // Skip is this is merely redefining part of a super-register.
+    if (RedefinesSuperRegPart(MI, MO, TRI))
+      continue;
+
     assert((isUnused(Reg) || isReserved(Reg)) &&
            "Re-defining a live register!");
     setUsed(Reg);
@@ -194,7 +224,7 @@ void RegScavenger::backward() {
     unsigned Reg = MO.getReg();
     assert(isUsed(Reg));
     if (!isReserved(Reg))
-      setUnused(Reg);
+      setUnused(Reg, MI);
   }
 
   // Process uses.