[llvm-dev] llvm-stress crash
Matthias Braun via llvm-dev
llvm-dev at lists.llvm.org
Tue Mar 14 15:04:03 PDT 2017
> On Mar 14, 2017, at 7:37 AM, Jonas Paulsson via llvm-dev <llvm-dev at lists.llvm.org> wrote:
>
> Hi,
>
> Using llvm-stress, I got a crash after Post-RA pseudo expansion, with machine verifier.
>
> A 128 bit register
>
> %vreg233:subreg_l32<def,read-undef> = LLCRMux %vreg119; GR128Bit:%vreg233 GRX32Bit:%vreg119
>
> gets spilled:
>
> %vreg265:subreg_l32<def,read-undef> = LLCRMux %vreg119; GR128Bit:%vreg265 GRX32Bit:%vreg119
> ST128 %vreg265, <fi#10>, 0, %noreg; mem:ST16[FixedStack10](align=8) GR128Bit:%vreg265
>
> -> regalloc
>
> %R5L<def> = LLCRMux %R6L, %R4Q<imp-def>
> ST128 %R4Q<kill>, <fi#10>, 0, %noreg; mem:ST16[FixedStack10](align=8)
>
> -> pseudo expansion
>
> %R5L<def> = LLCR %R6L
> STG %R4D<kill>, %R15D, 200, %noreg; mem:ST16[FixedStack7](align=8)
> STG %R5D<kill>, %R15D, 208, %noreg; mem:ST16[FixedStack7](align=8)
>
> *** Bad machine code: Using an undefined physical register ***
> - function: autogen_SD29355
> - basic block: BB#19 CF257 (0x4cb6b00)
> - instruction: STG
> - operand 0: %R4D<kill>
>
> So, it seems that vreg233 had only the low 64 bits defined to begin with, the upper 64 are undefined.
> Then this interval is spilled with the ST128 pseudo. After expansion, both 64 bit parts are spilled,
> where naturally the upper half is undefined.
The annoying problem here is that we have no way to mark a register as partially undef in LLVM, so when you break bigger uses apart you don't know that one of the halves is completely undefined now.
Mindlessly adding read-undef to both register is wrong however (as that semantically means you can do whatever with the use like replacing it with a completely different register). As recomputing liveness at this point to know whether one of the halfes is completely undefined is expensive and complicated I added an exception to the MachineVerifier for this which most other targets should be using:
// If there is an additional implicit-use of a super register we stop
// here. By definition we are fine if the super register is not
// (completely) dead, if the complete super register is dead we will
// get a report for its operand.
basically you leave a implicit use of the super register around to indicate that your original/higher level operation is about that super register and the verifier shouldn't care if a subregister is undefined.
- Matthias
More information about the llvm-dev
mailing list