[PATCH] Handle sub-ranges in frange == and != operators [PR126637]
Aldy Hernandez <[email protected]> Thu, 6 Aug 2026 16:20:34 +0200
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
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.
Pushed.
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.
---
gcc/range-op-float.cc | 20 +++++-----------
gcc/testsuite/gcc.dg/tree-ssa/pr126637.c | 29 ++++++++++++++++++++++++
2 files changed, 35 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126637.c
diff --git a/gcc/range-op-float.cc b/gcc/range-op-float.cc
index 628c1d365b1..ba6af5851c2 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 00000000000..68b4f4c0c39
--- /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;
+}
--
2.47.3