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

Reply via email to