[Bug middle-end/93806] Wrong optimization: instability of floating-point results with -funsafe-math-optimizations leads to nonsense
rguenther at suse dot de
gcc-bugzilla@gcc.gnu.org
Fri Feb 21 08:49:00 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93806
--- Comment #18 from rguenther at suse dot de <rguenther at suse dot de> ---
On Fri, 21 Feb 2020, bugdal at aerifal dot cx wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93806
>
> --- Comment #12 from Rich Felker <bugdal at aerifal dot cx> ---
> To me the meaning of internal consistency is very clear: that the semantics of
> the C language specification are honored and that the only valid
> transformations are those that follow the "as-if rule". Since C without Annex F
> allows arbitrarily awful floating point results, your example in comment 11 is
> fine. Each instance of 1/a can evaluate to a different value. They could even
> evaluate to random values. However, if you had written:
>
> int b = 1/a == 1/0.;
> int c = b;
> return b == c;
>
> then the function must necessarily return 1, because the single instance of
> 1/a==1/0. in the abstract machine has a single value, either 0 or 1, and in the
> abstract machine that value is stored to b, then copied to c, and b and c
> necessarily have the same value. While I don't think it's likely that GCC would
> mess up this specific example, it seems that it currently _can_ make
> transformations such that a more elaborate version of the same idea would be
> broken.
GCC indeed happily evaluates a floating-point expression multiple times,
for example for
void foo(float a, float b, float *x, float *y)
{
float tem = a + b;
*x = tem - a;
*y = tem - b;
}
I would expect GCC to turn this into
*x = (a + b) - a;
*y = (a + b) - b;
and then simplify further to b and a. Does this violate the "as-if rule"?
It certainly affects the result when a + b == a.
Note the fortran frontend uses the PAREN_EXPR which is an association
barrier to prevent optimizations across boundaries the language
standard places (parens IIRC). That still doesn't prevent GCC from
evaluating a single expression multiple times and possibly
doing different association inside the expression - so it still
violates the as-if rule. Classical transforms involve tail-duplication
of blocks but also loop unrolling if we happen to duplicate loop
invariant expressions.
So I guess the "as-if rule" can practically not be honored by an
optimized compiler.
More information about the Gcc-bugs
mailing list