This patch simply adds an op2_range to operator_div which returns
non-zero if the LHS is not undefined. This means given and integral
division:
x = y / z
'z' will have a range of [-INF, -1] [1, +INF] after execution of the
statement.
This is relatively straightforward and resolves the PR, but I also get
that we might not want to proliferate an inferred range of undefined
behavior at this late stage.
OK for trunk, or defer to stage 1? Are there any flags that need to be
checked to make this valid?
Bootstrapped on x86_64-pc-linux-gnu with no regressions.
Andrew
From 83260dd7c035a2317a6a5083d70288c3fdaf6ab4 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Tue, 21 Jan 2025 11:49:12 -0500
Subject: [PATCH] infer non-zero for integral division RHS.
Adding op2_range for operator_div allows ranger to notice the divisor
is non-zero after execution.
PR tree-optimization/95801
gcc/
* range-op.cc (operator_div::op2_range): New.
gcc/testsuite/
* gcc.dg/tree-ssa/pr95801.c: New.
---
gcc/range-op.cc | 16 ++++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/pr95801.c | 13 +++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr95801.c
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 6310ce27f03..e6aeefd436f 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2408,8 +2408,11 @@ operator_widen_mult_unsigned::wi_fold (irange &r, tree type,
class operator_div : public cross_product_operator
{
using range_operator::update_bitmask;
+ using range_operator::op2_range;
public:
operator_div (tree_code div_kind) { m_code = div_kind; }
+ bool op2_range (irange &r, tree type, const irange &lhs, const irange &,
+ relation_trio) const;
virtual void wi_fold (irange &r, tree type,
const wide_int &lh_lb,
const wide_int &lh_ub,
@@ -2429,6 +2432,19 @@ static operator_div op_floor_div (FLOOR_DIV_EXPR);
static operator_div op_round_div (ROUND_DIV_EXPR);
static operator_div op_ceil_div (CEIL_DIV_EXPR);
+// Set OP2 to non-zero if the LHS isn't UNDEFINED.
+bool
+operator_div::op2_range (irange &r, tree type, const irange &lhs,
+ const irange &, relation_trio) const
+{
+ if (!lhs.undefined_p ())
+ {
+ r.set_nonzero (type);
+ return true;
+ }
+ return false;
+}
+
bool
operator_div::wi_op_overflows (wide_int &res, tree type,
const wide_int &w0, const wide_int &w1) const
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr95801.c b/gcc/testsuite/gcc.dg/tree-ssa/pr95801.c
new file mode 100644
index 00000000000..c3c80a045cf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr95801.c
@@ -0,0 +1,13 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-evrp" }
+
+int always1(int a, int b) {
+ if (a / b)
+ return b != 0;
+ return 1;
+}
+
+// If b != 0 is optimized by recognizing divide by 0 cannot happen,
+// there should be no PHI node.
+
+// { dg-final { scan-tree-dump-not "PHI" "evrp" } }
--
2.45.0