On 04/01/2024 15:24, David Brown via Gcc-help wrote:
On 04/01/2024 16:03, Segher Boessenkool wrote:
On Thu, Jan 04, 2024 at 03:51:23PM +0100, David Brown via Gcc-help wrote:
This is a general limitation in GCC, as far as I know. I have come
across it myself (in my case it was the "-fwrapv" flag). As far as I
remember from a previous discussion long ago, there is no easy
workaround.
What are the expected semantics? That depends on the use case, so on
what the user expects. If the compiler inlines the function and picks
either set of options, it may do something the user wanted to avoid.
Not good.
Yes, I realise that's a key problem.
What I wanted in my own case was that this function:
#pragma GCC push_options
#pragma GCC optimize("-fwrapv")
inline int32_t add(int32_t x, int32_t y) {
return x + y;
}
#pragma GCC pop_options
would work exactly as though I had :
inline int32_t add(int32_t x, int32_t y) {
return (int32_t) ((uint32_t) x + (uint32_t) y);
}
The user can always write exactly what the user wants, instead :-)
In my case, I wrote it in that second version! But had "-fwrapv" worked
through inlining, it would have been convenient and neat, especially as
I had several related functions (for a wrapping-integer class).
More generally, I think the expected semantics are that the additional
options apply to code inside the function, and at the boundary you don't
care which set of options apply. So if you have normal floating point
code that sets "x", and then call an inline function with -ffast-math
using "x" as a parameter and returning "y", then the inlined could can
assume "x" is finite and not a NaN, and the later code can assume the
returned value "y" is similarly finite. If the calculations for "x"
produce a NaN, then the code will be UB - that's the programmer's fault.
Maybe we could have an option -fallow-inlining-that-changes-semantics?
Not sure if people will actually find that useful, but at least they
cannot say they weren't warned if they use that ;-)
Segher
The general problem here is that the AST does not carry enough
information to handle all these cases within a single function. To
merge wrap/no-wrap code, for example, we'd need separate codes for ADD,
SUBTRACT, MULTIPLY, etc.
At present that 'state' is carried globally, which makes merging
impossible without losing the state information.