Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

EFLAGS can end up as a live-out and crash stackmaps #21264

Open Quuxplusone opened 10 years ago

Quuxplusone commented 10 years ago
Bugzilla Link PR21265
Status NEW
Importance P normal
Reported by kmod@dropbox.com
Reported on 2014-10-13 17:41:18 -0700
Last modified on 2015-11-10 13:47:50 -0800
Version trunk
Hardware PC Linux
CC atrick@apple.com, jsweval@arxan.com, llvm-bugs@lists.llvm.org
Fixed by commit(s)
Attachments eflags.ll (1070 bytes, application/octet-stream)
Blocks
Blocked by
See also
Created attachment 13198
Test code -- run "llc eflags.ll" to reproduce

I've run into a situation where EFLAGS can end up as a live-out; here's a
snippet of the code before doing a block-merging optimization in
BranchFolding.cpp:

BB#1: derived from LLVM BB %1
    Live Ins: %RBP
    Predecessors according to CFG: BB#0
        %EAX<def> = MOV32r0 %EFLAGS<imp-def,dead>
        TEST8rr %AL, %AL, %EFLAGS<imp-def>, %EAX<imp-use,kill>
        JNE_4 <BB#4>, %EFLAGS<imp-use,kill>
        JMP_4 <BB#4>
    Successors according to CFG: BB#4(1048576)

BB#4: derived from LLVM BB %5
    Live Ins: %RBP
    Predecessors according to CFG: BB#1
        PATCHPOINT 30702560, 13, 8383728, 0, 0, <regmask>, %RSP<imp-def>, %RAX<imp-def,dead>, ...
        %RBP<def> = POP64r %RSP<imp-def>, %RSP<imp-use>
        RETQ

First we remove the extraneous JNE and JMP in BB#1:

BB#1: derived from LLVM BB %1
    Live Ins: %RBP
    Predecessors according to CFG: BB#0
        %EAX<def> = MOV32r0 %EFLAGS<imp-def,dead>
        TEST8rr %AL, %AL, %EFLAGS<imp-def>, %EAX<imp-use,kill>
    Successors according to CFG: BB#4(1048576)

BB#4: derived from LLVM BB %5
    Live Ins: %RBP
    Predecessors according to CFG: BB#1
        PATCHPOINT 30702560, 13, 8383728, 0, 0, <regmask>, %RSP<imp-def>, %RAX<imp-def,dead>, ...
        %RBP<def> = POP64r %RSP<imp-def>, %RSP<imp-use>
        RETQ

Then BB#4 gets merged in, resulting in this:

BB#1: derived from LLVM BB %1
    Live Ins: %RBP
    Predecessors according to CFG: BB#0
        %EAX<def> = MOV32r0 %EFLAGS<imp-def,dead>
        TEST8rr %AL, %AL, %EFLAGS<imp-def>, %EAX<imp-use,kill>
        PATCHPOINT 30702560, 13, 8383728, 0, 0, <regmask>, %RSP<imp-def>, %RAX<imp-def,dead>, ...
        %RBP<def> = POP64r %RSP<imp-def>, %RSP<imp-use>
        RETQ

In the removing of the JNE, we got rid of the instruction that kills EFLAGS,
without changing the TEST8rr instruction to mark it as a dead def.  Then when
we calculate liveness for the patchpoint, it looks like EFLAGS is supposed to
be alive there, tripping an assert in the stackmaps code.  I'm not sure if
anything else is affected by this, since it happens pretty late in the pipeline.

Not sure if this is related to http://llvm.org/bugs/show_bug.cgi?id=11132 --
seems like a similar result but might happen differently?
Quuxplusone commented 10 years ago

Attached eflags.ll (1070 bytes, application/octet-stream): Test code -- run "llc eflags.ll" to reproduce

Quuxplusone commented 10 years ago

Backward liveness should not consider EFLAGS to be live at the patchpoint. I'm not sure what the issue is here.

Quuxplusone commented 10 years ago

Oops, sorry got myself somewhat confused; EFLAGS gets added to the live set not by the stackmaps liveness analysis, which is backwards and correct like you mention, but by the forward analysis done in BranchFolder::MaintainLiveIns.