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? :)

Reply via email to