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.

llvm-svn: 361781
This commit is contained in:
Matt Arsenault 2019-05-27 20:37:31 +00:00
parent cfbc69e813
commit cece848032
2 changed files with 93 additions and 1 deletions

View File

@ -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 VirtReg) {
// 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 VirtReg) {
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(MachineInstr &MI) {
// 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;

View File

@ -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
...