https://gcc.gnu.org/g:b9c9f9350ca8cb8d0a59cb99b5e48f6f7328adc6
commit r17-3038-gb9c9f9350ca8cb8d0a59cb99b5e48f6f7328adc6 Author: Aldy Hernandez <[email protected]> Date: Thu Aug 6 07:01:38 2026 +0000 Handle sub-ranges in frange == and != operators [PR126637] When the operands do not intersect, == and != still allow equality if each range holds a zero of opposite sign, hence -0.0 == 0.0. The check for this looked at the hull endpoints, ignoring the inner sub-range boundaries. With sub-ranges the zero can be inner, e.g. [-1.0, -0.0][1.0, 1.0] with hull [-1.0, 1.0], so it was missed and e.g. "e != 0.0" folded to true. Tested on ppc64le Linux: regstrap and LAPACK. PR tree-optimization/126637 gcc/ChangeLog: * range-op-float.cc (operator_equal::fold_range): Use the contains_zero_p method to detect a contained zero instead of inspecting the hull endpoints. (operator_not_equal::fold_range): Likewise. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/pr126637.c: New test. Diff: --- gcc/range-op-float.cc | 20 ++++++-------------- gcc/testsuite/gcc.dg/tree-ssa/pr126637.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc index 628c1d365b19..ba6af5851c26 100644 --- a/gcc/range-op-float.cc +++ b/gcc/range-op-float.cc @@ -656,13 +656,9 @@ operator_equal::fold_range (irange &r, tree type, tmp.intersect (op2); if (tmp.undefined_p ()) { - // If one range is [whatever, -0.0] and another - // [0.0, whatever2], we don't know anything either, - // because -0.0 == 0.0. - if ((real_iszero (&op1.upper_bound ()) - && real_iszero (&op2.lower_bound ())) - || (real_iszero (&op1.lower_bound ()) - && real_iszero (&op2.upper_bound ()))) + // If one range contains -0.0 and another +0.0, we don't know + // anything either, because -0.0 == 0.0. + if (op1.contains_zero_p () && op2.contains_zero_p ()) r = range_true_and_false (type); else r = range_false (type); @@ -797,13 +793,9 @@ operator_not_equal::fold_range (irange &r, tree type, tmp.intersect (op2); if (tmp.undefined_p ()) { - // If one range is [whatever, -0.0] and another - // [0.0, whatever2], we don't know anything either, - // because -0.0 == 0.0. - if ((real_iszero (&op1.upper_bound ()) - && real_iszero (&op2.lower_bound ())) - || (real_iszero (&op1.lower_bound ()) - && real_iszero (&op2.upper_bound ()))) + // If one range contains -0.0 and another +0.0, we don't know + // anything either, because -0.0 == 0.0. + if (op1.contains_zero_p () && op2.contains_zero_p ()) r = range_true_and_false (type); else r = range_true (type); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126637.c b/gcc/testsuite/gcc.dg/tree-ssa/pr126637.c new file mode 100644 index 000000000000..68b4f4c0c395 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126637.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +/* e's range is [-1.0, -0.0][1.0, 1.0], which contains -0.0, so e != 0.0 + must not fold to true since -0.0 == 0.0. */ + +static double *a; +static void +b (int c) +{ + int d = 1; + double e = 1.0; + a = &e; + while (1) + { + if (!(e ? e : 4.0 < -c)) + break; + e = d - 1; + *a = -e; + d = 2; + } +} + +int +main () +{ + b (0); + return 0; +}
