https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107608

--- Comment #11 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #10)
> Some extra food for thought:
> void bar (void);
> 
> void
> foo (double x)
> {
>   if (x >= -16.0 && x <= 16.0)
>     {
>       double y = x + 32.0;
>       double z = y * 42.5;
>       if (z < 600.0 || z > 3000.0)
>       bar ();
>     }
> }
> with the usual default -O2 aka -O2 -ftrapping-math.
> frange can correctly prove that bar () will be never called and with -O2
> -fno-trapping-math it is perfectly fine to optimize the whole function out,
> z is known to be [680., 2040.] and not NaN.
> Now, even the comparisons aren't strictly needed, comparisons trap only on
> NaNs
> (< and > are not quiet, so any kind of them, but after all, frange doesn't
> track sNaNs vs. qNaNs) and we know z is not NaN.  But x comparisons can
> raise invalid on NaNs (both qNaN and sNaN), the addition is known not to
> raise invalid (x is not NaN), nor overflow (limited range), not sure right
> now if it can raise underflow or inexact, but at least the latter quite
> possibly.  The multiplication I'm quite sure can raise inexact though,
> so I think we need to keep everything until the z = computation, and either
> replace the comparison(s) of z with some dummy (asm?) use of z, or keep the
> comparisons but say turn the bar () call into __builtin_unreachable () or
> __builtin_trap () and make sure we don't optimize away the former later?
> 
> The reason I want to show this is mainly that even when the actual operation
> (comparisons here) we'd like to fold into constant are known not to raise
> any exceptions (and we should use frange info to find that out), it might be
> some intermediate calculation that might still raise exceptions.
> 
> I was considering to do some hack at least in my Fedora test mass rebuilds
> this month like for flag_trapping_math pretend no floating point range is
> singleton, but that still wouldn't cover comparisons.

For the comparisons I think we need to split them out of the GIMPLE_COND
(who do not have side-effects), so like with -fnon-call-exceptions do

    _3 = z < 6.0e+2;
    if (_3 != 0) goto <D.2749>; else goto <D.2751>;

then we can simplify the GIMPLE_CONDs just fine, we just need to keep
the comparison in some way.

For sNaN vs. qNaN I suppose we can use a tree predicate and go by
the kind of definition we see - sNaNs can only appear via a few
constrained operations (loads and init from a sNaN literal).

Reply via email to