[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" } } */