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).