The short answer is that our underlying infrastructure in Clang/LLVM is
different and our mechanism has to be slightly different.
Different implementation, same user interface. We shouldn't pass the
pain of our broken infrastructure to the user, but fix it or work
around it until we have fixed our infrastructure.
I'd rather have an incomplete pragma that breaks on anything but zero
than have a new pragma that will have to be ifdef'd on any other
compiler. So, in a nutshell:
#pragma GCC optimize 0
--> ok
#pragma GCC optimize 1|2|3
--> pre-processor warning not implemented (and ignored), not enabled
unless -Wall
A way to control optimization levels per-function has been proposed several
times in the past (see for example
http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061527.html ), but the
community has never reached a consensus on the idea; I think last time the
problem was that there were design issues with the PassManager in LLVM which
at the time was being redesigned (but as far as I know even the redesigned
version does not allow per-function control on optimizations).
You are correct. I have implemented a similar mechanism (for loop
optimizations) in the old pass manager that has been propagated by the
new one, but no generic solution exists.
IIRC, the main issue was with inlining. With no optimization we can
easily say "don't inline", but with optimize 2 vs -O 3 (or
vice-versa), there's no easy answer. What will the O2 inlined on O3
function be? Do we suppress *all* inlining of forced-opt functions? If
we do, we won't be doing O2 on it any more, but a subset. It's
complex.
FWIW, GCC produces inconsistent results for all combinations of pragma
vs. -O options...
The only
consensus that was reached was to implement a function attribute to disable
local optimizations for this specific use case - i.e. 'optnone'.
Yes, that was the easy one. There is another case that this is
interesting, heavily optimise a specific function, ie. #pragma GCC
optimize 3" on -O1. Anything else will be madness anyway, and GCC
doesn't seem to care much either.
What we could do is to define one behaviour for inlining (say add
neverinline) on all optimization levels. Then we turn a problem of
definition to one of optimisation.
However, we do have to change the pass manager...
Therefore, providing a pragma like "#pragma gcc optimize" that however deals
with only one case (i.e. optimization level zero) would cause confusion.
Ideally if we want to have such pragma we should implement the full feature,
but there is no consensus on that at the moment, so we have to use a
different approach.
#pragma optnone also causes confusion (it's unknown) and adds incompatibility.
I agree that the best solution would be to implement the full #pragma
optimize feature. We just don't want to restart the full debate (with the
risk of not reaching consensus again), and we'd rather settle for the
low-hanging fruit in the short term.
The cost of doing this is too high. You'll be moving from "our
problem" to "our users' problem" by forcing them to ifdef their code
forever.
As we note in the spec, if we ever implement the full #pragma optimize in
clang/LLVM then #pragma optnone will just become obsolete and deprecated. So
this proposal does not hinder any future work on the full #pragma optimize
feature.
Nor does adding "#pragma GCC optimize 0" from the start. With the
added bonus that Clang already ignores "optimize N".
cheers,
--renato