Skip to content

Commit ade2276

Browse files
[RegAllocFast] Ensure live-in vregs get reloaded after INLINEASM_BR spills
We have already ensured in 9cec2b2 that `INLINEASM_BR` output operands get spilled onto the stack, both in the fallthrough path and in the indirect targets. Since reloads of live-ins values into physical registers contextually happen after all MIR instructions (and ops) have been visited, make sure such loads are placed at the start of the block, but after prologues or `INLINEASM_BR` spills, as otherwise this may cause stale values to be read from the stack. Fixes: #74483, #110251.
1 parent 376aa74 commit ade2276

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

llvm/lib/CodeGen/RegAllocFast.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,8 @@ class RegAllocFastImpl {
391391
bool mayLiveOut(Register VirtReg);
392392
bool mayLiveIn(Register VirtReg);
393393

394+
bool mayBeSpillFromInlineAsmBr(const MachineInstr &MI) const;
395+
394396
void dumpState() const;
395397
};
396398

@@ -491,6 +493,21 @@ static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A,
491493
return IndexA < IndexB;
492494
}
493495

496+
/// Returns true if \p MI is a spill of a live-in physical register in a block
497+
/// targeted by an INLINEASM_BR. Such spills must precede reloads of live-in
498+
/// virtual registers, so that we do not reload from an uninitialized stack
499+
/// slot.
500+
bool RegAllocFastImpl::mayBeSpillFromInlineAsmBr(const MachineInstr &MI) const {
501+
int FI;
502+
auto *MBB = MI.getParent();
503+
if (MBB->isInlineAsmBrIndirectTarget() && TII->isStoreToStackSlot(MI, FI) &&
504+
MFI->isSpillSlotObjectIndex(FI))
505+
for (const auto &Op : MI.operands())
506+
if (Op.isReg() && MBB->isLiveIn(Op.getReg()))
507+
return true;
508+
return false;
509+
}
510+
494511
/// Returns false if \p VirtReg is known to not live out of the current block.
495512
bool RegAllocFastImpl::mayLiveOut(Register VirtReg) {
496513
if (MayLiveAcrossBlocks.test(VirtReg.virtRegIndex())) {
@@ -648,8 +665,8 @@ MachineBasicBlock::iterator RegAllocFastImpl::getMBBBeginInsertionPoint(
648665
continue;
649666
}
650667

651-
// Most reloads should be inserted after prolog instructions.
652-
if (!TII->isBasicBlockPrologue(*I))
668+
// Skip prologues and inlineasm_br spills to place reloads afterwards.
669+
if (!TII->isBasicBlockPrologue(*I) && !mayBeSpillFromInlineAsmBr(*I))
653670
break;
654671

655672
// However if a prolog instruction reads a register that needs to be
@@ -736,6 +753,8 @@ bool RegAllocFastImpl::displacePhysReg(MachineInstr &MI, MCRegister PhysReg) {
736753
assert(LRI != LiveVirtRegs.end() && "datastructures in sync");
737754
MachineBasicBlock::iterator ReloadBefore =
738755
std::next((MachineBasicBlock::iterator)MI.getIterator());
756+
while (mayBeSpillFromInlineAsmBr(*ReloadBefore))
757+
++ReloadBefore;
739758
reload(ReloadBefore, VirtReg, LRI->PhysReg);
740759

741760
setPhysRegState(LRI->PhysReg, regFree);

llvm/test/CodeGen/X86/regallocfast-callbr-asm-spills-after-reload.mir

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,8 @@ body: |
5454
bb.3 (machine-block-address-taken, inlineasm-br-indirect-target):
5555
successors: %bb.2(0x80000000)
5656
57-
; FIXME: This is a miscompilation, as, despite spilling the value modified by the inlineasm_br,
58-
; the reload emitted still reads from an uninitialized stack slot.
59-
; CHECK: $ecx = MOV32rm %stack.2, 1, $noreg, 0, $noreg :: (load (s32) from %stack.2)
60-
; CHECK-NEXT: MOV32mr %stack.2, 1, $noreg, 0, $noreg, $eax :: (store (s32) into %stack.2)
57+
; CHECK: MOV32mr %stack.2, 1, $noreg, 0, $noreg, $eax :: (store (s32) into %stack.2)
58+
; CHECK-NEXT: $ecx = MOV32rm %stack.2, 1, $noreg, 0, $noreg :: (load (s32) from %stack.2)
6159
; CHECK-NEXT: $rax = MOV64rm %stack.3, 1, $noreg, 0, $noreg :: (load (s64) from %stack.3)
6260
; CHECK-NEXT: MOV32mr renamable $rax, 1, $noreg, 0, $noreg, killed renamable $ecx :: (store (s32))
6361
; CHECK-NEXT: JMP_1 %bb.2

0 commit comments

Comments
 (0)