When x <= y and the relation oracle knows VREL_GE, it can only mean
x == y. Similarly for x >= y with VREL_LE.
The oracle already derives the equality for the ranger. This is for
passes that rewrite the IL. Since this is a statement change it lives
in the simplifier, not range-ops.
DOM does this from its expression table. This patch just find a
better home for it. In a follow-up, I will replace the DOM code with
a simplify_using_ranges call.
Tested on ppc64le Linux.
Pushed.
gcc/ChangeLog:
* vr-values.cc (simplify_using_ranges::simplify_compare_using_ranges_1):
Fold a LE or GE test between two names to EQ when the relation
oracle implies it.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/vrp-le-ge-relation-1.c: New test.
---
.../gcc.dg/tree-ssa/vrp-le-ge-relation-1.c | 31 +++++++++++++++++++
gcc/vr-values.cc | 14 +++++++++
2 files changed, 45 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp-le-ge-relation-1.c
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp-le-ge-relation-1.c
b/gcc/testsuite/gcc.dg/tree-ssa/vrp-le-ge-relation-1.c
new file mode 100644
index 00000000000..5dd9d0751e4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp-le-ge-relation-1.c
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fdump-tree-evrp" } */
+
+/* i >= j where i <= j holds is i == j. */
+
+void frob (void);
+
+void __GIMPLE (ssa,startwith("evrp"))
+f (int i, int j)
+{
+ __BB(2):
+ if (i_1(D) <= j_2(D))
+ goto __BB3;
+ else
+ goto __BB5;
+
+ __BB(3):
+ if (i_1(D) >= j_2(D))
+ goto __BB4;
+ else
+ goto __BB5;
+
+ __BB(4):
+ frob ();
+ goto __BB5;
+
+ __BB(5):
+ return;
+}
+
+/* { dg-final { scan-tree-dump "if \\(i_1\\(D\\) == j_2\\(D\\)\\)" "evrp" } }
*/
diff --git a/gcc/vr-values.cc b/gcc/vr-values.cc
index c4edff871f0..11424c21d03 100644
--- a/gcc/vr-values.cc
+++ b/gcc/vr-values.cc
@@ -1209,6 +1209,20 @@ simplify_using_ranges::simplify_compare_using_ranges_1
(tree_code &cond_code, tr
}
}
}
+ // If OP0 >= OP1 and the relation between them is VREL_LE (or vice
+ // versa), we know OP0 == OP1.
+ else if ((cond_code == LE_EXPR || cond_code == GE_EXPR)
+ && gimple_range_ssa_p (op0)
+ && gimple_range_ssa_p (op1))
+ {
+ relation_kind rel = query->relation ().query (stmt, op0, op1);
+ if (relation_intersect (cond_code == LE_EXPR ? VREL_LE : VREL_GE, rel)
+ == VREL_EQ)
+ {
+ cond_code = EQ_EXPR;
+ happened = true;
+ }
+ }
// Try to simplify casted conditions.
if (simplify_casted_compare (cond_code, op0, op1))
happened = true;
--
2.53.0