[llvm-dev] Preventing function call from being optimized out in LTO

Johannes Doerfert via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 10 07:33:03 PDT 2020


On 6/9/20 1:01 PM, Shishir V Jessu via llvm-dev wrote:
> Hello,
>
> I am adding function calls to an LLVM link-time optimization (LTO) pass,
> using the IRBuilder::CreateCall method. I want these calls to remain in the
> final x86 binary at any optimization level, but on levels -O2 and -O3, some
> of these calls are being optimized out.
>
> So far, I've tried adding each function in the program (excluding LLVM
> intrinsics) to the llvm.used set, and I've also set noinline and optnone
> attributes on each function in the program. This has allowed me to
> retain *most,
> *but not all, of the calls I've added with IRBuilder::CreateCall.
>
> Furthermore, I have confirmed that all the calls I've created are present
> in the LLVM IR that results immediately after my pass. Thus, I know some
> future LTO pass is optimizing out some of these calls.
>
> How can I ensure that none of the calls I add are optimized out? Thanks for
> your help!

The answer, in short, is:

  Don't run any optimizations/normalizations or, better, only place 
calls where they are not statically dead.


Basically, if you want optimization, O2/O3, you get them. We even have 
"reaosnable"

way to tell optimizations to ignore some part of the code, e.g., 
optnone, but even then,

some trivial things will be removed (think `if (false) foo();`). That 
said, you can

make the code "conditionally life" to avoid this. There are many ways, 
one would be

something like:


Before:

```

int foo(int a) {

   if (a > 3)

     return a-1;

   return 0;

}

```


After:

```

int return_zero() __attribute__((pure)) // linked in as object file


int foo(int a) {

    if (return_zero() != 0)

      goto calls;


    if (a > 3) {

call1:

       my_new_call(1, a);

       return a-1;

    }


call2:

    my_new_call(2, a);

    return 0;


calls:

    switch (return_zero()) {

    case 1: goto call1;

    case 2: goto call2;

    default:

            goto call2;

    };

}


Now even if you inline the above for a call site like

`foo(0)`, the `my_new_call(1, a)` call site will still

be considered life, thus not be removed.


Hope this helps.


>
> Best,
> Shishir Jessu
>
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://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/20200610/68cc9f54/attachment.html>


More information about the llvm-dev mailing list