[PATCH] range-op.cc: add VREL_EQ relation effect for div and mod [PR126745]

Daniel Barboza <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
For res = a / b and a == b, set 'res' to one.

For res = a % b and a == b, set 'res' to zero.

Both are done by dom2/dom3 already.  With this change we're now
doing it earlier (with -O2) in evrp.

Bootstrapped and regtested in x86_64.

	PR tree-optimization/126745

gcc/ChangeLog:

	* range-op.cc (operator_div::op1_op2_relation_effect): add
	VREL_EQ range equal one for op1/op2 and op1%op2 if op1 == op2.

gcc/testsuite/ChangeLog:

	* gcc.dg/tree-ssa/pr126745.c: New test.
---
 gcc/range-op.cc                          | 36 ++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr126745.c | 16 +++++++++++
 2 files changed, 52 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126745.c

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index bb055623872..0311cef7d47 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2641,6 +2641,7 @@ operator_div::op1_op2_relation_effect (irange &lhs_range,
     return false;
 
   int_range<2> rel_range;
+  wide_int one;
 
   switch (rel)
     {
@@ -2652,6 +2653,10 @@ operator_div::op1_op2_relation_effect (irange &lhs_range,
 	      && wi::ge_p (op2_range.lower_bound (), 0, SIGNED)))
 	rel_range.set_zero (type);
       break;
+    case VREL_EQ:
+      one = wi::one (TYPE_PRECISION (type));
+      rel_range.set (type, one, one);
+      break;
     default:
       return false;
     }
@@ -4380,6 +4385,7 @@ class operator_trunc_mod : public range_operator
   using range_operator::op1_range;
   using range_operator::op2_range;
   using range_operator::update_bitmask;
+  using range_operator::op1_op2_relation_effect;
 public:
   virtual void wi_fold (irange &r, tree type,
 		        const wide_int &lh_lb,
@@ -4396,6 +4402,11 @@ public:
 			  relation_trio) const;
   void update_bitmask (irange &r, const irange &lh, const irange &rh) const
     { update_known_bitmask (r, TRUNC_MOD_EXPR, lh, rh); }
+  bool op1_op2_relation_effect (irange &lhs_range,
+				tree type,
+				const irange &op1_range,
+				const irange &op2_range,
+				relation_kind rel) const final override;
 } op_trunc_mod;
 
 void
@@ -4536,6 +4547,31 @@ operator_trunc_mod::op2_range (irange &r, tree type,
   return false;
 }
 
+bool
+operator_trunc_mod::op1_op2_relation_effect (irange &lhs_range,
+					     tree type,
+					     const irange &,
+					     const irange &,
+					     relation_kind rel) const
+{
+  if (rel == VREL_VARYING)
+    return false;
+
+  int_range<2> rel_range;
+
+  switch (rel)
+    {
+    case VREL_EQ:
+      rel_range.set_zero (type);
+      break;
+    default:
+      return false;
+    }
+
+  lhs_range.intersect (rel_range);
+  return true;
+}
+
 
 class operator_logical_not : public range_operator
 {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126745.c b/gcc/testsuite/gcc.dg/tree-ssa/pr126745.c
new file mode 100644
index 00000000000..77405653ba2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126745.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int f (int a, int b)
+{
+    if (a != b) __builtin_unreachable ();
+    return a / b;
+}
+/* { dg-final { scan-tree-dump-times "return 1;" 1 "evrp" } } */
+
+int f2 (int a, int b)
+{
+    if (a != b) __builtin_unreachable ();
+    return a % b;
+}
+/* { dg-final { scan-tree-dump-times "return 0;" 1 "evrp" } } */
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.