[llvm-commits] [llvm] r107193 - in /llvm/trunk: lib/CodeGen/RegAllocFast.cpp test/CodeGen/ARM/2010-06-29-PartialRedefFastAlloc.ll

Jakob Stoklund Olesen stoklund at 2pi.dk
Tue Jun 29 12:15:30 PDT 2010


Author: stoklund
Date: Tue Jun 29 14:15:30 2010
New Revision: 107193

URL: http://llvm.org/viewvc/llvm-project?rev=107193&view=rev
Log:
Fix the handling of partial redefines in the fast register allocator.

A partial redefine needs to be treated like a tied operand, and the register
must be reloaded while processing use operands.

This fixes a bug where partially redefined registers were processed as normal
defs with a reload added. The reload could clobber another use operand if it was
a kill that allowed register reuse.

Added:
    llvm/trunk/test/CodeGen/ARM/2010-06-29-PartialRedefFastAlloc.ll
Modified:
    llvm/trunk/lib/CodeGen/RegAllocFast.cpp

Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocFast.cpp?rev=107193&r1=107192&r2=107193&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegAllocFast.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegAllocFast.cpp Tue Jun 29 14:15:30 2010
@@ -515,7 +515,6 @@
   bool New;
   tie(LRI, New) = LiveVirtRegs.insert(std::make_pair(VirtReg, LiveReg()));
   LiveReg &LR = LRI->second;
-  bool PartialRedef = MI->getOperand(OpNum).getSubReg();
   if (New) {
     // If there is no hint, peek at the only use of this register.
     if ((!Hint || !TargetRegisterInfo::isPhysicalRegister(Hint)) &&
@@ -527,15 +526,7 @@
         Hint = DstReg;
     }
     allocVirtReg(MI, *LRI, Hint);
-    // If this is only a partial redefinition, we must reload the other parts.
-    if (PartialRedef && MI->readsVirtualRegister(VirtReg)) {
-      const TargetRegisterClass *RC = MRI->getRegClass(VirtReg);
-      int FI = getStackSpaceFor(VirtReg, RC);
-      DEBUG(dbgs() << "Reloading for partial redef: %reg" << VirtReg << "\n");
-      TII->loadRegFromStackSlot(*MBB, MI, LR.PhysReg, FI, RC, TRI);
-      ++NumLoads;
-    }
-  } else if (LR.LastUse && !PartialRedef) {
+  } else if (LR.LastUse) {
     // Redefining a live register - kill at the last use, unless it is this
     // instruction defining VirtReg multiple times.
     if (LR.LastUse != MI || LR.LastUse->getOperand(LR.LastOpNum).isUse())
@@ -571,10 +562,16 @@
   } else if (LR.Dirty) {
     if (isLastUseOfLocalReg(MO)) {
       DEBUG(dbgs() << "Killing last use: " << MO << "\n");
-      MO.setIsKill();
+      if (MO.isUse())
+        MO.setIsKill();
+      else
+        MO.setIsDead();
     } else if (MO.isKill()) {
       DEBUG(dbgs() << "Clearing dubious kill: " << MO << "\n");
       MO.setIsKill(false);
+    } else if (MO.isDead()) {
+      DEBUG(dbgs() << "Clearing dubious dead: " << MO << "\n");
+      MO.setIsDead(false);
     }
   } else if (MO.isKill()) {
     // We must remove kill flags from uses of reloaded registers because the
@@ -583,6 +580,9 @@
     // This would cause a second reload of %x into a different register.
     DEBUG(dbgs() << "Clearing clean kill: " << MO << "\n");
     MO.setIsKill(false);
+  } else if (MO.isDead()) {
+    DEBUG(dbgs() << "Clearing clean dead: " << MO << "\n");
+    MO.setIsDead(false);
   }
   assert(LR.PhysReg && "Register not assigned");
   LR.LastUse = MI;
@@ -625,7 +625,8 @@
     if (!MO.isReg()) continue;
     unsigned Reg = MO.getReg();
     if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg)) continue;
-    if (MO.isEarlyClobber() || MI->isRegTiedToDefOperand(i)) {
+    if (MO.isEarlyClobber() || MI->isRegTiedToDefOperand(i) ||
+        (MO.getSubReg() && MI->readsVirtualRegister(Reg))) {
       if (ThroughRegs.insert(Reg))
         DEBUG(dbgs() << " %reg" << Reg);
     }
@@ -649,6 +650,7 @@
     }
   }
 
+  SmallVector<unsigned, 8> PartialDefs;
   DEBUG(dbgs() << "Allocating tied uses and early clobbers.\n");
   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
     MachineOperand &MO = MI->getOperand(i);
@@ -663,6 +665,14 @@
       LiveRegMap::iterator LRI = reloadVirtReg(MI, i, Reg, 0);
       unsigned PhysReg = LRI->second.PhysReg;
       setPhysReg(MI, i, PhysReg);
+      // Note: we don't update the def operand yet. That would cause the normal
+      // def-scan to attempt spilling.
+    } else if (MO.getSubReg() && MI->readsVirtualRegister(Reg)) {
+      DEBUG(dbgs() << "Partial redefine: " << MO << "\n");
+      // Reload the register, but don't assign to the operand just yet.
+      // That would confuse the later phys-def processing pass.
+      LiveRegMap::iterator LRI = reloadVirtReg(MI, i, Reg, 0);
+      PartialDefs.push_back(LRI->second.PhysReg);
     } else if (MO.isEarlyClobber()) {
       // Note: defineVirtReg may invalidate MO.
       LiveRegMap::iterator LRI = defineVirtReg(MI, i, Reg, 0);
@@ -683,6 +693,10 @@
     for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS)
       UsedInInstr.set(*AS);
   }
+
+  // Also mark PartialDefs as used to avoid reallocation.
+  for (unsigned i = 0, e = PartialDefs.size(); i != e; ++i)
+    UsedInInstr.set(PartialDefs[i]);
 }
 
 void RAFast::AllocateBasicBlock() {
@@ -767,7 +781,10 @@
     // Mark physreg uses and early clobbers as used.
     // Find the end of the virtreg operands
     unsigned VirtOpEnd = 0;
-    bool hasTiedOps = false, hasEarlyClobbers = false, hasPhysDefs = false;
+    bool hasTiedOps = false;
+    bool hasEarlyClobbers = false;
+    bool hasPartialRedefs = false;
+    bool hasPhysDefs = false;
     for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
       MachineOperand &MO = MI->getOperand(i);
       if (!MO.isReg()) continue;
@@ -775,11 +792,15 @@
       if (!Reg) continue;
       if (TargetRegisterInfo::isVirtualRegister(Reg)) {
         VirtOpEnd = i+1;
-        if (MO.isUse())
+        if (MO.isUse()) {
           hasTiedOps = hasTiedOps ||
                                 TID.getOperandConstraint(i, TOI::TIED_TO) != -1;
-        else if (MO.isEarlyClobber())
-          hasEarlyClobbers = true;
+        } else {
+          if (MO.isEarlyClobber())
+            hasEarlyClobbers = true;
+          if (MO.getSubReg() && MI->readsVirtualRegister(Reg))
+            hasPartialRedefs = true;
+        }
         continue;
       }
       if (!Allocatable.test(Reg)) continue;
@@ -800,7 +821,8 @@
     // operands.
     // We didn't detect inline asm tied operands above, so just make this extra
     // pass for all inline asm.
-    if (MI->isInlineAsm() || hasEarlyClobbers || (hasTiedOps && hasPhysDefs)) {
+    if (MI->isInlineAsm() || hasEarlyClobbers || hasPartialRedefs ||
+        (hasTiedOps && hasPhysDefs)) {
       handleThroughOperands(MI, VirtDead);
       // Don't attempt coalescing when we have funny stuff going on.
       CopyDst = 0;

Added: llvm/trunk/test/CodeGen/ARM/2010-06-29-PartialRedefFastAlloc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2010-06-29-PartialRedefFastAlloc.ll?rev=107193&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/2010-06-29-PartialRedefFastAlloc.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/2010-06-29-PartialRedefFastAlloc.ll Tue Jun 29 14:15:30 2010
@@ -0,0 +1,22 @@
+; RUN: llc < %s -O0 -mcpu=cortex-a8 | FileCheck %s
+target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32"
+target triple = "thumbv7-apple-darwin10"
+
+; This tests the fast register allocator's handling of partial redefines:
+;
+;	%reg1026<def> = VMOVv16i8 0, pred:14, pred:%reg0
+;	%reg1028:dsub_1<def> = EXTRACT_SUBREG %reg1026<kill>, 1
+;
+; %reg1026 gets allocated %Q0, and if %reg1028 is reloaded for the partial redef,
+; it cannot also get %Q0.
+
+; CHECK: vmov.i8 q0, #0x0
+; CHECK-NOT: vld1.64 {d0,d1}
+; CHECK: vmov.f64 d3, d0
+
+define i32 @main(i32 %argc, i8** %argv) nounwind {
+entry:
+ %0 = shufflevector <2 x i64> undef, <2 x i64> zeroinitializer, <2 x i32> <i32 1, i32 2> ; <<2 x i64>> [#uses=1]
+ store <2 x i64> %0, <2 x i64>* undef, align 16
+ ret i32 undef
+}





More information about the llvm-commits mailing list