Fix a bug in the -regalloc=fast handling of exotic two-address instruction with
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Thu, 29 Jul 2010 00:52:19 +0000 (00:52 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Thu, 29 Jul 2010 00:52:19 +0000 (00:52 +0000)
multiple defs, like t2LDRSB_POST.

The first def could accidentally steal the physreg that the second, tied def was
required to be allocated to.

Now, the tied use-def is treated more like an early clobber, and the physreg is
reserved before allocating the other defs.

This would never be a problem when the tied def was the only def which is the
usual case.

This fixes MallocBench/gs for thumb2 -O0.

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

lib/CodeGen/RegAllocFast.cpp

index e34fcdbebba01d610c9c3ff98418fb523034c00c..66f83d823e21b1ce13b6d042c5ee2d2b3c656f3c 100644 (file)
@@ -847,13 +847,18 @@ void RAFast::AllocateBasicBlock() {
     // operands. If there are also physical defs, these registers must avoid
     // both physical defs and uses, making them more constrained than normal
     // operands.
+    // Similarly, if there are multiple defs and tied operands, we must make sure
+    // the same register is allocated to uses and defs.
     // We didn't detect inline asm tied operands above, so just make this extra
     // pass for all inline asm.
     if (MI->isInlineAsm() || hasEarlyClobbers || hasPartialRedefs ||
-        (hasTiedOps && hasPhysDefs)) {
+        (hasTiedOps && (hasPhysDefs || TID.getNumDefs() > 1))) {
       handleThroughOperands(MI, VirtDead);
       // Don't attempt coalescing when we have funny stuff going on.
       CopyDst = 0;
+      // Pretend we have early clobbers so the use operands get marked below.
+      // This is not necessary for the common case of a single tied use.
+      hasEarlyClobbers = true;
     }
 
     // Second scan.
@@ -874,14 +879,17 @@ void RAFast::AllocateBasicBlock() {
 
     MRI->addPhysRegsUsed(UsedInInstr);
 
-    // Track registers defined by instruction - early clobbers at this point.
+    // Track registers defined by instruction - early clobbers and tied uses at
+    // this point.
     UsedInInstr.reset();
     if (hasEarlyClobbers) {
       for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
         MachineOperand &MO = MI->getOperand(i);
-        if (!MO.isReg() || !MO.isDef()) continue;
+        if (!MO.isReg()) continue;
         unsigned Reg = MO.getReg();
         if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue;
+        // Look for physreg defs and tied uses.
+        if (!MO.isDef() && !MI->isRegTiedToDefOperand(i)) continue;
         UsedInInstr.set(Reg);
         for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS)
           UsedInInstr.set(*AS);