[PATCH] gold, libLTO: Add new flags to support bit set lowering.

Duncan P. N. Exon Smith dexonsmith at apple.com
Wed Mar 18 12:46:48 PDT 2015

> On 2015-Mar-18, at 12:08, Peter Collingbourne <peter at pcc.me.uk> wrote:
> On Wed, Mar 18, 2015 at 09:16:54AM -0400, Rafael EspĂ­ndola wrote:
>>> I don't think this should be a problem; there is no user-visible behaviour
>>> change when using the supported way of enabling control flow integrity.
>>> The only supported way to enable CFI for the user to supply -fsanitize=cfi*
>>> at link time as well as at compile time. (Admittedly this should be
>>> documented better.) The LowerBitSets pass only has an effect on the module
>>> if -fsanitize=cfi* was passed as compile time. And the related change
>>> http://reviews.llvm.org/D8402 modifies the Clang driver to supply the
>>> lowerbitsets flag if -fsanitize=cfi* is supplied at link time.
>> If the pass does nothing if a given flag is not present, why not
>> always run the pass and avoid the option?
> I would like a way to run only a couple of passes at link time if CFI is
> enabled and optimizations are enabled but LTO is not specifically enabled. In
> particular, I've found that running only simplifycfg and globaldce makes a
> significant difference in binary size (with the full LTO pipeline, a Chrome
> binary is 179424536 bytes, and with simplifycfg+globaldce it is 160340400
> bytes). So we need some way to communicate an optimization level to the
> linker so that it knows what level to use.
> Duncan and I discussed this on IRC last night, and we agreed that module
> flags inserted at compile time would be the best way to communicate this
> information. I thought further about how this could work and I came up with
> something relatively simple.
> The solution I have in mind is that a module flag named "LTO Opt Level"
> will control the opt level. An opt level of 0 runs no optimization passes, a
> level of 1 runs only simplifycfg and globaldce and 2 runs the entire LTO pass
> pipeline. -flto causes us to set the flag to 2, otherwise -O >= 1 causes us
> to set it to 1, otherwise it is 0. When modules have conflicting opt levels,
> we pick the maximum.
> I have patches that implement this and I'll upload them later today.

I'm still not sure about the high-level approach.  I didn't put together
that you'd need to send an "LTO Opt Level" through module flags (I just
understood the -lowerbitsets part).

I think there may be a minefield of semantic issues with using the LTO
pipeline when the user hasn't specifically enabled LTO.  Can you point
me at the discussion on the list about this so I can catch up?  (I'm
sorry I missed it.)

For example, what semantics do you expect in the following case?

    $ clang -O3 -flto a.c
    $ clang -O1 -fsanitize=cfi b.c
    $ clang a.o b.o

Here, a.c is supposed to be compiled with LTO but b.c isn't.  I'm not
sure how you would merge the LTO Opt Level in this case (among other

IMO, the following flow makes more sense (but maybe this was already

  - If -fno-lto, run -lowerbitsets near the end of the -cc1 opt
    pipeline.  *Do not* enable -flto.
  - If -flto, skip -lowerbitsets in -cc1.
  - Leave the LTO pipeline alone, letting it always running
    -lowerbitsets near the end (it's a free pass if it has nothing
    to do).

More information about the llvm-commits mailing list