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

--- Comment #13 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Tamar Christina from comment #11)
> Testcase that triggers this
> 
> extern double tand_r16_x;
> extern int tand_r16_n;
> int tand_r16() { return tand_r16_n - tand_r16_x &&tand_r16_x * 0; }
> 
> at just -O3.
> 
> I can't bisect because the range outputs are correct, (at least from what I
> can tell in evrp).  It's the values before clamping that go wrong and stack
> smashing doesn't happen consistently so the bisect goes off course.
> 
> With the assert this always hits though.

At least on this testcase I see
2380          /* For +-DBL_MAX, instead of +-Inf use nexttoward (+-DBL_MAX,
+-LDBL_MAX)
2381             in a hypothetical wider type with the same mantissa precision
but
2382             larger exponent range; it is outside of range of double
values, but
2383             makes it clear it is just one ulp larger rather than infinite
amount
2384             larger.  */
2385          res = real_isneg (&dir) ? dconstm1 : dconst1;
2386          SET_REAL_EXP (&res, FLOAT_MODE_FORMAT (TYPE_MODE (type))->emax +
1);
never being triggered, yet it still attempts to set_significand with n >=
SIGNIFICANT_BITS.
This is on frange_nextafter with
-0x0.8p-1074 value towards +Inf, so the problem is that the value is larger
than smallest negative denormal but still not -0.
This has been introduced to fix PR109008 (two separate commits at least there)
and worked well before r17-2929 because the temporarily widened range hasn't
been used much, basically it was fed to the reverse operation which then did
frange_arithmetic or something similar which performed some operation and then
rounded to the corresponding mode, even when the widened range itself wasn't.
Now, with r17-2929 we actually try to frange_nextafter for these 0.5ulp in
between some numbers or up to 1ulp above/below largest negative/positive
representable finite in frange_fusible_p and that isn't prepared to handle
those.
Either we tweak frange_nextafter to handle those, or frange_fusible_p, or don't
try to union the float_widened_lhs_range pairs and handle it manually, etc.
If you ask where it would be easiest, I think it would be in
float_widened_lhs_range, because there we know the original min/max before the
widening, so we can actually check there what is nextafter of the original max1
+ 1ulp and nextafter of the original min2 - 1ulp and if max1 + 1ulp >= min2
-1ulp, we should merge the two pairs, otherwise we shouldn't.

Reply via email to