[llvm-dev] MachineSink optimization in code containing a setjmp

TB Schardl via llvm-dev llvm-dev at lists.llvm.org
Tue Oct 13 14:24:09 PDT 2015


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>


More information about the llvm-dev mailing list