[gcc r17-3335] range-op: add VREL_LT relation effect for div [PR126748]

Daniel Barboza via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:53b803a0d48df023a11231f9c43917ca9e33279d

commit r17-3335-g53b803a0d48df023a11231f9c43917ca9e33279d
Author: Daniel Barboza <[email protected]>
Date:   Wed Aug 12 06:24:27 2026 -0300

    range-op: add VREL_LT relation effect for div [PR126748]
    
    Given A div B, if we know for certain that A and B are positive
    and A < B, we can infer that A div B is zero.
    
    Bootstrapped and regression tested in x86_64, aarch64 and riscv64.
    
            PR tree-optimization/126748
    
    gcc/ChangeLog:
    
            * range-op.cc (class operator_div): declarations.
            (operator_div::op1_op2_relation_effect): add op1/op2 relation
            range equal zero for op1/op2 if op1 < op2 and both op1 and op2
            are positives.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/tree-ssa/pr126748.c: New test.

Diff:
---
 gcc/range-op.cc                          | 35 ++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/tree-ssa/pr126748.c | 26 ++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 39c1271f0806..71f1a91f0790 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2499,6 +2499,7 @@ class operator_div : public cross_product_operator
 {
   using range_operator::update_bitmask;
   using range_operator::op2_range;
+  using range_operator::op1_op2_relation_effect;
 public:
   operator_div (tree_code div_kind) { m_code = div_kind; }
   bool op2_range (irange &r, tree type, const irange &lhs, const irange &,
@@ -2511,6 +2512,11 @@ public:
   virtual bool wi_op_overflows (wide_int &res, tree type,
 				const wide_int &, const wide_int &)
     const final override;
+  bool op1_op2_relation_effect (irange &lhs_range,
+				tree type,
+				const irange &op1_range,
+				const irange &op2_range,
+				relation_kind rel) const final override;
   void update_bitmask (irange &r, const irange &lh, const irange &rh)
     const final override
     { update_known_bitmask (r, m_code, lh, rh); }
@@ -2624,6 +2630,35 @@ operator_div::wi_fold (irange &r, tree type,
   gcc_checking_assert (!r.undefined_p ());
 }
 
+bool
+operator_div::op1_op2_relation_effect (irange &lhs_range,
+				       tree type,
+				       const irange &op1_range,
+				       const irange &op2_range,
+				       relation_kind rel) const
+{
+  if (rel == VREL_VARYING)
+    return false;
+
+  int_range<2> rel_range;
+
+  switch (rel)
+    {
+    /* op1/op2 = 0 if op1 < op2 and both op1 and op2
+       are known positives.  */
+    case VREL_LT:
+      if (TYPE_UNSIGNED (type)
+	  || (wi::ge_p (op1_range.lower_bound (), 0, SIGNED)
+	      && wi::ge_p (op2_range.lower_bound (), 0, SIGNED)))
+	rel_range.set_zero (type);
+      break;
+    default:
+      return false;
+    }
+
+  lhs_range.intersect (rel_range);
+  return true;
+}
 
 class operator_exact_divide : public operator_div
 {
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126748.c b/gcc/testsuite/gcc.dg/tree-ssa/pr126748.c
new file mode 100644
index 000000000000..063187a904c1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126748.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+unsigned f(unsigned a, unsigned b)
+{
+    if (b >= a) __builtin_unreachable();
+    return b / a;
+}
+
+int fs(int a, int b)
+{
+  a = __builtin_abs(a);
+  b = __builtin_abs(b);
+  if (b >= a) __builtin_unreachable();
+  return b / a;
+}
+
+/* This can't be simplified.  */
+int fs2(int a, int b)
+{
+  if (b >= a) __builtin_unreachable();
+  return b / a;
+}
+
+/* { dg-final { scan-tree-dump-times "return 0;" 2 "evrp" } } */
+/* { dg-final { scan-tree-dump-times " / " 1 "evrp" } } */
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.