TB Schardl via llvm-dev
2015-Oct-13 20:29 UTC
[llvm-dev] MachineSink optimization in code containing a setjmp
Hello LLVM-dev, I think I've found an issue with the MachineSink optimization on a program that uses setjmp. It looks like MachineSink will happily move a machine instruction into a following machine basic block (not necessarily a successor), even when that later block can be reached through a setjmp. Here is some example debug output from llc that I'm seeing: Sinking along critical edge. Sink instr %vreg8<def,tied1> = ADD64rr %vreg14<tied0>, %vreg31, %EFLAGS<imp-def,dead>; GR64:%vreg8,%vreg14,%vreg31 into block BB#11: Predecessors according to CFG: BB#8 BB#10 BB#32 ... EH_SjLj_Setup <BB#36>, <regmask> Successors according to CFG: BB#34 BB#36 Sinking along critical edge. Sink instr %vreg8<def,tied1> = ADD64rr %vreg14<tied0>, %vreg31, %EFLAGS<imp-def,dead>; GR64:%vreg8,%vreg14,%vreg31 into block BB#35: Predecessors according to CFG: BB#34 BB#36 .. Successors according to CFG: BB#12(12) BB#13(20) In this case, it looks like MachineSink moves the ADD64rr instruction from BB#4 into BB#26, which post-dominates both BB#25 and BB#27. This movement becomes a problem, I think, when the arguments of the moved instruction are spilled onto the stack. Here is the final assembly of the affected basic blocks: .LBB0_19 ... movq %rbp, -104(%rbp) movq %rsp, -88(%rbp) movq $.LBB0_42, 8(%r15) #EH_SjLj_Setup .LBB0_42 # BB#20: movq -176(%rbp), %rdi # 8-byte Reload xorl %ecx, %ecx jmp .LBB0_21 .LBB0_42: movl $1, %ecx movq -176(%rbp), %rdi # 8-byte Reload .LBB0_21: movq -168(%rbp), %rax # 8-byte Reload addq -144(%rbp), %rax # 8-byte Folded Reload movq %rax, -168(%rbp) # 8-byte Spill In my code, because of the setjmp, basic block .LBB0_21 ends up executing twice, causing the addition to execute twice and produce an incorrect result. It seems like moving non-idempotent operations past a setjmp in this way should be incorrect, because a corresponding longjmp can cause that operation to execute twice. Am I missing something in this reasoning? Thank you in advance for your help. I apologize for not having a small test program handy. The program in which I found this issue is somewhat large and complex. Cheers, TB -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151013/0bf192a6/attachment.html>
Daniel Berlin via llvm-dev
2015-Oct-13 21:04 UTC
[llvm-dev] MachineSink optimization in code containing a setjmp
JUst to be clear: is the setjmp function marked returns_twice? On Tue, Oct 13, 2015 at 1:29 PM, TB Schardl via llvm-dev <llvm-dev at lists.llvm.org> wrote:> Hello LLVM-dev, > > I think I've found an issue with the MachineSink optimization on a program > that uses setjmp. It looks like MachineSink will happily move a machine > instruction into a following machine basic block (not necessarily a > successor), even when that later block can be reached through a setjmp. > Here is some example debug output from llc that I'm seeing: > > Sinking along critical edge. > Sink instr %vreg8<def,tied1> = ADD64rr %vreg14<tied0>, %vreg31, > %EFLAGS<imp-def,dead>; GR64:%vreg8,%vreg14,%vreg31 > into block BB#11: > Predecessors according to CFG: BB#8 BB#10 BB#32 > ... > EH_SjLj_Setup <BB#36>, <regmask> > Successors according to CFG: BB#34 BB#36 > Sinking along critical edge. > Sink instr %vreg8<def,tied1> = ADD64rr %vreg14<tied0>, %vreg31, > %EFLAGS<imp-def,dead>; GR64:%vreg8,%vreg14,%vreg31 > into block BB#35: > Predecessors according to CFG: BB#34 BB#36 > .. > Successors according to CFG: BB#12(12) BB#13(20) > > In this case, it looks like MachineSink moves the ADD64rr instruction from > BB#4 into BB#26, which post-dominates both BB#25 and BB#27. This movement > becomes a problem, I think, when the arguments of the moved instruction are > spilled onto the stack. Here is the final assembly of the affected basic > blocks: > > .LBB0_19 > ... > movq %rbp, -104(%rbp) > movq %rsp, -88(%rbp) > movq $.LBB0_42, 8(%r15) > #EH_SjLj_Setup .LBB0_42 > # BB#20: > movq -176(%rbp), %rdi # 8-byte Reload > xorl %ecx, %ecx > jmp .LBB0_21 > .LBB0_42: > movl $1, %ecx > movq -176(%rbp), %rdi # 8-byte Reload > .LBB0_21: > movq -168(%rbp), %rax # 8-byte Reload > addq -144(%rbp), %rax # 8-byte Folded Reload > movq %rax, -168(%rbp) # 8-byte Spill > > In my code, because of the setjmp, basic block .LBB0_21 ends up executing > twice, causing the addition to execute twice and produce an incorrect > result. > > It seems like moving non-idempotent operations past a setjmp in this way > should be incorrect, because a corresponding longjmp can cause that > operation to execute twice. Am I missing something in this reasoning? > > Thank you in advance for your help. I apologize for not having a small test > program handy. The program in which I found this issue is somewhat large > and complex. > > Cheers, > TB > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >
TB Schardl via llvm-dev
2015-Oct-13 21:24 UTC
[llvm-dev] MachineSink optimization in code containing a setjmp
We're using the llvm.eh.sjlj.setjmp() intrinsic. From the IR, the declaration of the intrinsic is only marked nounwind, but all calls to the intrinsic are marked returns_twice. TB On Tue, Oct 13, 2015 at 5:04 PM, Daniel Berlin <dberlin at dberlin.org> wrote:> JUst to be clear: is the setjmp function marked returns_twice? > > > On Tue, Oct 13, 2015 at 1:29 PM, TB Schardl via llvm-dev > <llvm-dev at lists.llvm.org> wrote: > > Hello LLVM-dev, > > > > I think I've found an issue with the MachineSink optimization on a > program > > that uses setjmp. It looks like MachineSink will happily move a machine > > instruction into a following machine basic block (not necessarily a > > successor), even when that later block can be reached through a setjmp. > > Here is some example debug output from llc that I'm seeing: > > > > Sinking along critical edge. > > Sink instr %vreg8<def,tied1> = ADD64rr %vreg14<tied0>, %vreg31, > > %EFLAGS<imp-def,dead>; GR64:%vreg8,%vreg14,%vreg31 > > into block BB#11: > > Predecessors according to CFG: BB#8 BB#10 BB#32 > > ... > > EH_SjLj_Setup <BB#36>, <regmask> > > Successors according to CFG: BB#34 BB#36 > > Sinking along critical edge. > > Sink instr %vreg8<def,tied1> = ADD64rr %vreg14<tied0>, %vreg31, > > %EFLAGS<imp-def,dead>; GR64:%vreg8,%vreg14,%vreg31 > > into block BB#35: > > Predecessors according to CFG: BB#34 BB#36 > > .. > > Successors according to CFG: BB#12(12) BB#13(20) > > > > In this case, it looks like MachineSink moves the ADD64rr instruction > from > > BB#4 into BB#26, which post-dominates both BB#25 and BB#27. This > movement > > becomes a problem, I think, when the arguments of the moved instruction > are > > spilled onto the stack. Here is the final assembly of the affected basic > > blocks: > > > > .LBB0_19 > > ... > > movq %rbp, -104(%rbp) > > movq %rsp, -88(%rbp) > > movq $.LBB0_42, 8(%r15) > > #EH_SjLj_Setup .LBB0_42 > > # BB#20: > > movq -176(%rbp), %rdi # 8-byte Reload > > xorl %ecx, %ecx > > jmp .LBB0_21 > > .LBB0_42: > > movl $1, %ecx > > movq -176(%rbp), %rdi # 8-byte Reload > > .LBB0_21: > > movq -168(%rbp), %rax # 8-byte Reload > > addq -144(%rbp), %rax # 8-byte Folded Reload > > movq %rax, -168(%rbp) # 8-byte Spill > > > > In my code, because of the setjmp, basic block .LBB0_21 ends up executing > > twice, causing the addition to execute twice and produce an incorrect > > result. > > > > It seems like moving non-idempotent operations past a setjmp in this way > > should be incorrect, because a corresponding longjmp can cause that > > operation to execute twice. Am I missing something in this reasoning? > > > > Thank you in advance for your help. I apologize for not having a small > test > > program handy. The program in which I found this issue is somewhat large > > and complex. > > > > Cheers, > > TB > > > > _______________________________________________ > > LLVM Developers mailing list > > llvm-dev at lists.llvm.org > > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev > > >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20151013/cc70dbf4/attachment.html>