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

David Blaikie via llvm-dev llvm-dev at lists.llvm.org
Tue Jun 9 16:08:34 PDT 2020


On Tue, Jun 9, 2020 at 2:32 PM Shishir V Jessu <shishir.jessu at utexas.edu>
wrote:

> Hi David,
>
> Sure! Here's a function in sqlite3 called verifyDbFile, compiled with -O3.
> This is what it looks like when the intermediate bitcode is emitted by
> clang: link <https://pastebin.com/L3PrK1ac>
>
> And here's what happens after I run opt -O3 (no additional command-line
> arguments) on the file containing this function: link
> <https://pastebin.com/rZHBm2iU>.
>
> I'm not 100% sure, but it seems like some pass within opt determines that
> a particular trap is guaranteed to occur on line 22, and so optimizes out
> the rest of the function, even though the pre-opt version of the function
> has the "optnone" attribute.
>
> Does this seem like intended behavior or some sort of bug? Is there any
> way to disable this behavior? Thanks!
>

Ah, OK, so the call is unconditionally dead based on local reasoning within
the function - not sure if that qualifies as a bug in the optnone
implementation. Even at -O0, we do some optimizations - just designed to be
benign ones, from a program behavior/debugging perspective, I suppose.

+Paul Robinson <paul.robinson at sony.com>  who had some hand in the
implementation of optnone, to see how he feels about it/whether he reckons
removing dead code at -O0/optnone is desirable or not.

But otherwise, if you can make the code not dead, that would thwart any
optimizations - eg: loading from a volatile variable (that could always be
false in reality) to determine the condition to branch to the code you want
to preserve.

- David


>
> Best,
> Shishir
>
> On Tue, Jun 9, 2020 at 3:53 PM David Blaikie <dblaikie at gmail.com> wrote:
>
>> On Tue, Jun 9, 2020 at 1:29 PM Shishir V Jessu <shishir.jessu at utexas.edu>
>> wrote:
>> >
>> > Hi David,
>> >
>> > Thanks for your detailed comments.
>> >
>> >> but without any interprocedural analysis, nor any optimization of the
>> body of the function, a call to an optnone function can still be removed if
>> the call is dead.
>> >
>> >
>> > I am not concerned with calls to an optnone function being removed, but
>> rather call-sites within an optnone function being removed. But although I
>> place "optnone" on a given function F, dead code in F still sometimes seems
>> to be potentially removed. Is there any way to prevent this from happening
>> at the linking stage (since the bitcode emitted by clang still includes all
>> my calls)?
>>
>> Oh, sorry - my misunderstanding. Could you provide an example of that
>> happening? (a specific optnone function IR and a specific 'opt'
>> command that optimizes that IR and modifies the optnone function in an
>> unexpected/undesirable way) - that could be a bug.
>>
>> - Dave
>>
>> >
>> > Thanks,
>> > Shishir
>> >
>> > On Tue, Jun 9, 2020 at 2:12 PM David Blaikie <dblaikie at gmail.com>
>> wrote:
>> >>
>> >> On Tue, Jun 9, 2020 at 11:54 AM Shishir V Jessu <
>> shishir.jessu at utexas.edu> wrote:
>> >>>
>> >>> Hi David,
>> >>>
>> >>> By "dead" do you mean unreachable?
>> >>
>> >>
>> >> Yep!
>> >>
>> >>>
>> >>> My understanding was that the removal of dead code is simply another
>> optimization,
>> >>
>> >>
>> >> It is, yes.
>> >>
>> >>>
>> >>> which should be disabled after adding "optnone"
>> >>
>> >>
>> >> Nah - optnone just means "don't optimize this function" (nor do
>> interprocedural analysis to optimize the call site based on details of the
>> implementation of this function - treat it as though this function were in
>> another translation unit/module that the compiler has no visibility into) -
>> but without any interprocedural analysis, nor any optimization of the body
>> of the function, a call to an optnone function can still be removed if the
>> call is dead.
>> >>
>> >>>
>> >>> (and adding the function to llvm.used so the function doesn't later
>> get deleted entirely).
>> >>
>> >>
>> >> llvm.used is there to preserve functions that don't otherwise need to
>> exist - it sounds to me like this isn't a useful tool for your situation -
>> if you manage to preserve the call then the function will be retained
>> (unless it's defined as "available externally" - then the definition of the
>> funcion could be removed, leaving only a declaration). It sounds like you
>> need to preserve the call - so if you succeed at that, then the function
>> body/definition should be retained without the need for llvm.used.
>> >>
>> >>>
>> >>> I am instrumenting certain basic blocks in an LLVM pass, and would
>> like to compile a binary which structures things the same way the LLVM pass
>> does, to analyze some behavior.
>> >>
>> >>
>> >> Hmm, can't quite picture that from what you've described, sorry.
>> >>
>> >>>
>> >>> I observe that my calls are not removed on -O0 and -O1 for several
>> programs, so it should be the case that the calls are removed on higher
>> optimization levels - but then adding "optnone" isn't protecting all of
>> those calls from being removed.
>> >>
>> >>
>> >> Any number of optimizations might make more code provably dead & then
>> removed, losing your calls.
>> >>
>> >> - Dave
>> >>
>> >>>
>> >>>
>> >>> If you have any more insight I'd appreciate it! Thanks for your help.
>> >>>
>> >>> On Tue, Jun 9, 2020 at 1:13 PM David Blaikie <dblaikie at gmail.com>
>> wrote:
>> >>>>
>> >>>> optnone on such functions should suffice - well, unless the calls
>> turn out to be dead & I don't think there's anything you can do to thwart
>> dead code removal. So what are you trying to preserve the function calls
>> for?
>> >>>>
>> >>>> On Tue, Jun 9, 2020 at 11:01 AM Shishir V Jessu via llvm-dev <
>> llvm-dev at lists.llvm.org> 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!
>> >>>>>
>> >>>>> 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/20200609/4eafa025/attachment.html>


More information about the llvm-dev mailing list