Created attachment 20951
reduced reproducer
Running the attached reproducer gives:
llc -run-pass greedy -verify-regalloc -mtriple x86_64-- -o - remat-undef-
use.mir
********** MACHINEINSTRS **********
# Machine code for function test: IsSSA, NoPHIs, TracksLiveness
Frame Objects:
fi#-1: size=1504, align=8, fixed, at location [SP+8]
fi#0: size=4, align=4, at location [SP+8]
0B bb.0:
successors: %bb.1(0x80000000); %bb.1(100.00%)
16B dead %3:gr32 = MOV32rm $rsp, 1, $noreg, 8, $noreg :: (load 4 from
%fixed-stack.0, align 16)
32B %1:gr32 = MOV32rm %stack.0, 1, $noreg, 0, $noreg :: (load 4 from
%stack.0)
48B bb.1:
; predecessors: %bb.0, %bb.1
successors: %bb.1(0x80000000); %bb.1(100.00%)
56B %2:gr32 = MOV32rm $rsp, 1, $noreg, 8, $noreg :: (load 4 from %fixed-
stack.0, align 16)
64B INLINEASM &nop [sideeffect] [attdialect],
$0:[regdef:GR32_ABCD_and_GR32_BSI], implicit %2:gr32
80B INLINEASM &nop [sideeffect] [attdialect], $0:[clobber], implicit-def
dead early-clobber $rax, $1:[clobber], implicit-def dead early-clobber $rbx,
$2:[clobber], implicit-def dead early-clobber $rcx, $3:[clobber], implicit-def
dead early-clobber $rdx, $4:[clobber], implicit-def dead early-clobber $rsi,
$5:[clobber], implicit-def dead early-clobber $rdi, $6:[clobber], implicit-def
dead early-clobber $rbp, $7:[clobber], implicit-def dead early-clobber $r8,
$8:[clobber], implicit-def dead early-clobber $r9, $9:[clobber], implicit-def
dead early-clobber $r10, $10:[clobber], implicit-def dead early-clobber $r11,
$11:[clobber], implicit-def dead early-clobber $r12, $12:[clobber], implicit-
def dead early-clobber $r13, $13:[clobber], implicit-def dead early-clobber
$r14, $14:[clobber], implicit-def dead early-clobber $r15
96B JMP_1 %bb.1
# End machine code for function test.
*** Bad machine code: Instruction loads from dead spill slot ***
- function: test
- basic block: %bb.0 (0x4514ef8) [0B;48B)
- instruction: 32B %1:gr32 = MOV32rm %stack.0, 1, $noreg, 0, $noreg ::
(load 4 from %stack.0)
- operand 1: %stack.0
Live stack: SS#0 EMPTY 0@x weight:0.000000e+00
*** Bad machine code: Instruction ending live segment on dead slot has no dead
flag ***
- function: test
- basic block: %bb.0 (0x4514ef8) [0B;48B)
- instruction: 32B %1:gr32 = MOV32rm %stack.0, 1, $noreg, 0, $noreg ::
(load 4 from %stack.0)
- liverange: [32r,32d:0) 0@32r
- v. register: %1
- segment: [32r,32d:0)
LLVM ERROR: Found 2 machine code errors.
The problem with "Instruction ending live segment on dead slot has no dead
flag" might be a duplicate of https://bugs.llvm.org/show_bug.cgi?id=33024
Running with -debug we can see this:
Inline spilling GR32:%0 [16r,112B:0) 0@16r weight:4.188229e+00
From original %0
remat: 56r %2:gr32 = MOV32rm $rsp, 1, $noreg, 8, $noreg :: (load 4 from %fixed-stack.0, align 16)
64e INLINEASM &nop [sideeffect] [attdialect], $0:[regdef:GR32_ABCD_and_GR32_BSI], implicit killed %2:gr32
All defs dead: dead %0:gr32 = MOV32rm $rsp, 1, $noreg, 8, $noreg :: (load 4
from %fixed-stack.0, align 16)
Remat created 1 dead defs.
Deleting dead def 16r dead %0:gr32 = MOV32rm $rsp, 1, $noreg, 8, $noreg ::
(load 4 from %fixed-stack.0, align 16)
1 registers to spill after remat.
Merged spilled regs: SS#0 EMPTY 0@x weight:0.000000e+00
spillAroundUses %0
folded: 32r %1:gr32 = MOV32rm %stack.0, 1, $noreg, 0, $noreg :: (load 4 from %stack.0)
Afaict InlineSpiller is trying to add remats for the fixed-stack load. So it
inserts a load before the use inside the loop (start of bb.1), but since the
use in the COPY (in bb.0) is undef it isn't replaced by a remat, instead we get
a reload from a new spill slot. Although, there is no spill to the spill slot
(perhaps because the code thinks that we rematerialized all uses(?)).
Not sure where to solve this. Isn't it unfortunate to have these undef uses
(and dead defs) lingering around when doing the register allocation? Maybe we
could cleanup up those at the very beginning? Or should the remat be smarter
and replace the undef COPY with an IMPLICIT_DEF?
remat-undef-use.mir
(1199 bytes, text/plain)