https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107569
--- Comment #24 from Aldy Hernandez <aldyh at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #22)
> Folding statement: _2 = __builtin_pow (1.0e+1, _1);
> Global Exported: _2 = [frange] double [0.0 (0x0.0p+0), +Inf] +NAN
> The +NAN looks suspicious, shouldn't that be +-NAN ?
> Of course once we handle POW builtins, if we are smart enough we should see
> that it is 10.0 ** [INT_MIN, -1] and so [0.0, 1.0e-1] (plus some larger ulp
> error because library functions aren't exactly 0.5ulp precise all the time).
> But when we don't know what __builtin_pow does (from frange perspective), I
> don't see what
> tells us that NAN with negative sign can't appear.
Yeah, that +NAN looks very suspicious. For that matter, it took me a while to
figure out how we know that _2 can't be negative, because we don't have any
range-op entries for __builtin_pow.
So...here's a trick to figure this out: --param=ranger-debug=tracegori
You'll see in the *evrp dump:
Folding statement: _2 = __builtin_pow (1.0e+1, _1);
45 range_of_stmt (_2) at stmt _2 = __builtin_pow (1.0e+1, _1);
TRUE : (45) range_of_stmt (_2) [frange] double [0.0 (0x0.0p+0), +Inf]
+NAN
46 range_of_expr(_1) at stmt _2 = __builtin_pow (1.0e+1, _1);
TRUE : (46) range_of_expr (_1) [frange] double VARYING +-NAN
47 range_of_stmt (_2) at stmt _2 = __builtin_pow (1.0e+1, _1);
TRUE : (47) cached (_2) [frange] double [0.0 (0x0.0p+0), +Inf] +NAN
Global Exported: _2 = [frange] double [0.0 (0x0.0p+0), +Inf] +NAN
So ranger was able to figure out immediately that _2 was positive.
Andrew added smarts to break into any given place, so we can break where the
counter is 45:
(gdb) break breakpoint if index == 45
Yes, amazingly there's only one function named breakpoint() in the entire
compiler ;-).
If you single step from there on, we run into:
if (gimple_stmt_nonnegative_warnv_p (call, &strict_overflow_p))
r.set_nonnegative (type);
else if (gimple_call_nonnull_result_p (call)
|| gimple_call_nonnull_arg (call))
r.set_nonzero (type);
else
r.set_varying (type);
IIRC, we had some discussion upstream about the meaning of set_nonnegative, and
we all agreed that nuking -NAN was the right thing. Neat, huh? :)