<div dir="ltr"><br><br><div class="gmail_quote">On Wed, Mar 18, 2015 at 12:49 PM Duncan P. N. Exon Smith <<a href="mailto:dexonsmith@apple.com">dexonsmith@apple.com</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
> On 2015-Mar-18, at 12:08, Peter Collingbourne <<a href="mailto:peter@pcc.me.uk" target="_blank">peter@pcc.me.uk</a>> wrote:<br>
><br>
> On Wed, Mar 18, 2015 at 09:16:54AM -0400, Rafael Espíndola wrote:<br>
>>> I don't think this should be a problem; there is no user-visible behaviour<br>
>>> change when using the supported way of enabling control flow integrity.<br>
>>><br>
>>> The only supported way to enable CFI for the user to supply -fsanitize=cfi*<br>
>>> at link time as well as at compile time. (Admittedly this should be<br>
>>> documented better.) The LowerBitSets pass only has an effect on the module<br>
>>> if -fsanitize=cfi* was passed as compile time. And the related change<br>
>>> <a href="http://reviews.llvm.org/D8402" target="_blank">http://reviews.llvm.org/D8402</a> modifies the Clang driver to supply the<br>
>>> lowerbitsets flag if -fsanitize=cfi* is supplied at link time.<br>
>><br>
>> If the pass does nothing if a given flag is not present, why not<br>
>> always run the pass and avoid the option?<br>
><br>
> I would like a way to run only a couple of passes at link time if CFI is<br>
> enabled and optimizations are enabled but LTO is not specifically enabled. In<br>
> particular, I've found that running only simplifycfg and globaldce makes a<br>
> significant difference in binary size (with the full LTO pipeline, a Chrome<br>
> binary is 179424536 bytes, and with simplifycfg+globaldce it is 160340400<br>
> bytes). So we need some way to communicate an optimization level to the<br>
> linker so that it knows what level to use.<br>
><br>
> Duncan and I discussed this on IRC last night, and we agreed that module<br>
> flags inserted at compile time would be the best way to communicate this<br>
> information. I thought further about how this could work and I came up with<br>
> something relatively simple.<br>
> </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
> The solution I have in mind is that a module flag named "LTO Opt Level"<br>
> will control the opt level. An opt level of 0 runs no optimization passes, a<br>
> level of 1 runs only simplifycfg and globaldce and 2 runs the entire LTO pass<br>
> pipeline. -flto causes us to set the flag to 2, otherwise -O >= 1 causes us<br>
> to set it to 1, otherwise it is 0. When modules have conflicting opt levels,<br>
> we pick the maximum.<br>
><br>
> I have patches that implement this and I'll upload them later today.<br>
<br></blockquote><div><br></div><div><div>I very strongly disagree with this approach.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I'm still not sure about the high-level approach.  I didn't put together<br>
that you'd need to send an "LTO Opt Level" through module flags (I just<br>
understood the -lowerbitsets part).<br>
<br></blockquote><div><br></div><div>Not only that, but the idea of specifying flags that enable optimizations via the module I'm fairly against (see the global opt thread as well).</div><div><br></div><div>A possibility is to have a global "this pass must be run" node, but even that's problematic as you get either a) abuse, or b) conflicts on ordering etc.</div><div><br></div><div>I think we need to take a step back here and define what needs to happen for the LTO pipeline and when things need to be run.</div><div><br></div><div>-eric</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I think there may be a minefield of semantic issues with using the LTO<br>
pipeline when the user hasn't specifically enabled LTO.  Can you point<br>
me at the discussion on the list about this so I can catch up?  (I'm<br>
sorry I missed it.)<br>
<br>
For example, what semantics do you expect in the following case?<br>
<br>
    $ clang -O3 -flto a.c<br>
    $ clang -O1 -fsanitize=cfi b.c<br>
    $ clang a.o b.o<br>
<br>
Here, a.c is supposed to be compiled with LTO but b.c isn't.  I'm not<br>
sure how you would merge the LTO Opt Level in this case (among other<br>
problems).<br>
<br>
IMO, the following flow makes more sense (but maybe this was already<br>
discussed?):<br>
<br>
  - If -fno-lto, run -lowerbitsets near the end of the -cc1 opt<br>
    pipeline.  *Do not* enable -flto.<br>
  - If -flto, skip -lowerbitsets in -cc1.<br>
  - Leave the LTO pipeline alone, letting it always running<br>
    -lowerbitsets near the end (it's a free pass if it has nothing<br>
    to do).<br>
<br></blockquote><div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
______________________________<u></u>_________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu" target="_blank">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/<u></u>mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>