[llvm] r361781 - RegAllocFast: Set MayLiveAcrossBlocks when allocating uses

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon May 27 13:37:31 PDT 2019


Author: arsenm
Date: Mon May 27 13:37:31 2019
New Revision: 361781

URL: http://llvm.org/viewvc/llvm-project?rev=361781&view=rev
Log:
RegAllocFast: Set MayLiveAcrossBlocks when allocating uses

Setting mayLiveOut based only on use instructions after allocating the
def block did not work if the use block was allocated before the def
block, since the virtual register uses were already removed.

Fixes bug 41973.

Added:
    llvm/trunk/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir
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=361781&r1=361780&r2=361781&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegAllocFast.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegAllocFast.cpp Mon May 27 13:37:31 2019
@@ -226,6 +226,7 @@ namespace {
                 MCPhysReg PhysReg);
 
     bool mayLiveOut(unsigned VirtReg);
+    bool mayLiveIn(unsigned VirtReg);
 
     void dumpState();
   };
@@ -270,8 +271,10 @@ bool RegAllocFast::mayLiveOut(unsigned V
 
   // If this block loops back to itself, it would be necessary to check whether
   // the use comes after the def.
-  if (MBB->isSuccessor(MBB))
+  if (MBB->isSuccessor(MBB)) {
+    MayLiveAcrossBlocks.set(TargetRegisterInfo::virtReg2Index(VirtReg));
     return true;
+  }
 
   // See if the first \p Limit uses of the register are all in the current
   // block.
@@ -288,6 +291,24 @@ bool RegAllocFast::mayLiveOut(unsigned V
   return false;
 }
 
+/// Returns false if \p VirtReg is known to not be live into the current block.
+bool RegAllocFast::mayLiveIn(unsigned VirtReg) {
+  if (MayLiveAcrossBlocks.test(TargetRegisterInfo::virtReg2Index(VirtReg)))
+    return !MBB->pred_empty();
+
+  // See if the first \p Limit def of the register are all in the current block.
+  static const unsigned Limit = 8;
+  unsigned C = 0;
+  for (const MachineInstr &DefInst : MRI->def_instructions(VirtReg)) {
+    if (DefInst.getParent() != MBB || ++C >= Limit) {
+      MayLiveAcrossBlocks.set(TargetRegisterInfo::virtReg2Index(VirtReg));
+      return !MBB->pred_empty();
+    }
+  }
+
+  return false;
+}
+
 /// Insert spill instruction for \p AssignedReg before \p Before. Update
 /// DBG_VALUEs with \p VirtReg operands with the stack slot.
 void RegAllocFast::spill(MachineBasicBlock::iterator Before, unsigned VirtReg,
@@ -1083,6 +1104,11 @@ void RegAllocFast::allocateInstruction(M
         // There is no need to allocate a register for an undef use.
         continue;
       }
+
+      // Populate MayLiveAcrossBlocks in case the use block is allocated before
+      // the def block (removing the vreg uses).
+      mayLiveIn(Reg);
+
       LiveReg &LR = reloadVirtReg(MI, I, Reg, CopyDstReg);
       MCPhysReg PhysReg = LR.PhysReg;
       CopySrcReg = (CopySrcReg == Reg || CopySrcReg == PhysReg) ? PhysReg : 0;

Added: llvm/trunk/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir?rev=361781&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir (added)
+++ llvm/trunk/test/CodeGen/X86/regalloc-fast-missing-live-out-spill.mir Mon May 27 13:37:31 2019
@@ -0,0 +1,66 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=x86_64-grtev4-linux-gnu -run-pass=regallocfast -o - %s | FileCheck %s
+
+# Bug 41973. Make sure %12 is detected as live out of %bb.0, even
+# though the use is allocated before the def block %bb.3. Previously
+# mayLiveOut only recorded on defs, and would not find the virtual
+# register use if it had already been replace with a physical
+# register.
+
+---
+name:            main
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: main
+  ; CHECK: bb.0:
+  ; CHECK:   successors: %bb.3(0x80000000)
+  ; CHECK:   liveins: $edi, $rsi
+  ; CHECK:   MOV64mr %stack.0, 1, $noreg, 0, $noreg, killed $rsi :: (store 8 into %stack.0)
+  ; CHECK:   JMP_1 %bb.3
+  ; CHECK: bb.1:
+  ; CHECK:   successors:
+  ; CHECK: bb.2:
+  ; CHECK:   successors: %bb.3(0x80000000)
+  ; CHECK:   $rax = MOV64rm %stack.1, 1, $noreg, 0, $noreg :: (load 8 from %stack.1)
+  ; CHECK:   renamable $ecx = MOV32r0 implicit-def $eflags
+  ; CHECK:   renamable $rdx = SUBREG_TO_REG 0, killed renamable $ecx, %subreg.sub_32bit
+  ; CHECK:   MOV64mi32 killed renamable $rax, 1, $noreg, 0, $noreg, 0 :: (volatile store 8)
+  ; CHECK:   MOV64mr %stack.0, 1, $noreg, 0, $noreg, killed $rdx :: (store 8 into %stack.0)
+  ; CHECK: bb.3:
+  ; CHECK:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK:   $rax = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)
+  ; CHECK:   renamable $ecx = MOV32r0 implicit-def dead $eflags
+  ; CHECK:   renamable $rdx = SUBREG_TO_REG 0, killed renamable $ecx, %subreg.sub_32bit
+  ; CHECK:   MOV64mr %stack.1, 1, $noreg, 0, $noreg, killed $rdx :: (store 8 into %stack.1)
+  ; CHECK:   JMP64r killed renamable $rax
+  bb.0:
+    liveins: $edi, $rsi
+
+    %4:gr64 = COPY $rsi
+    %2:gr32 = COPY $edi
+    %3:gr32 = COPY killed %2
+    %5:gr64 = COPY killed %4
+    %13:gr64 = COPY %5
+    JMP_1 %bb.3
+
+  bb.1:
+    successors:
+
+
+  bb.2:
+    %0:gr64 = COPY %12
+    %10:gr32 = MOV32r0 implicit-def $eflags
+    %11:gr64 = SUBREG_TO_REG 0, %10, %subreg.sub_32bit
+    MOV64mi32 %0, 1, $noreg, 0, $noreg, 0 :: (volatile store 8)
+    %13:gr64 = COPY %11
+
+  bb.3:
+    successors: %bb.2, %bb.1
+
+    %1:gr64 = COPY %13
+    %9:gr32 = MOV32r0 implicit-def dead $eflags
+    %8:gr64 = SUBREG_TO_REG 0, killed %9, %subreg.sub_32bit
+    %12:gr64 = COPY %8
+    JMP64r %1
+
+...




More information about the llvm-commits mailing list