On 3/28/25 10:36, Andrew MacLeod wrote:
On 3/28/25 03:19, Richard Biener wrote:
On Fri, Mar 28, 2025 at 12:28 AM Andrew MacLeod <amacl...@redhat.com>
wrote:
This patch fixes both 119471 and the remainder of 110992.
At issue is we do not recognize that if
"a * b != 0" , then neither "a" nor "b" can be zero.
This is fairly trivial with range-ops. op1_range and op2_range for
operator_mult are taught that if the LHS does not contain zero, than
neither does either operand.
Included are patches for trunk (gcc15), gcc14, and gcc13. All are
basically the same few lines.
I presume we want to wait for stage 1 to check this into trunk .
Bootstraps with no regressions on x86_64-pc-linux-gnu on all 3
branches. OK for gcc13 and gcc14 branches?
This is OK for branches only after it was on trunk. Since one of the
PRs is a regression it's technically OK for trunk now.
Richard.
OK, it should be perfectly safe. Committed to trunk.
Andrew
This patch was in trunk when gcc15 was forked, so gcc15 is already
covered. Attached are the patches for gcc14 and gcc13.
Bootstrapped with no regressions on x86_64-pc-linux-gnu.
Do you want me to check it in for either or both branches?
Andrew
From 7a7e91e59850e61b790571524d0bc337409694a7 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Thu, 27 Mar 2025 13:50:16 -0400
Subject: [PATCH 2/3] If the LHS does not contain zero, neither do multiply
operands.
Given ~[0,0] = op1 * op2, range-ops should determine that neither op1 nor
op2 is zero. Add this to the operator_mult for op1_range. op2_range
simply invokes op1_range, so both will be covered.
PR tree-optimzation/110992.c
PR tree-optimzation/119471.c
gcc/
* range-op.cc (operator_mult::op1_range): If the LHS does not
contain zero, return non-zero.
gcc/testsuite/
* gcc.dg/pr110992.c: New.
* gcc.dg/pr119471.c: New.
---
gcc/range-op.cc | 8 ++++++++
gcc/testsuite/gcc.dg/pr110992.c | 18 ++++++++++++++++++
gcc/testsuite/gcc.dg/pr119471.c | 19 +++++++++++++++++++
3 files changed, 45 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/pr110992.c
create mode 100644 gcc/testsuite/gcc.dg/pr119471.c
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 97a88dc7efa..275b3ae6891 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -1976,6 +1976,14 @@ operator_mult::op1_range (irange &r, tree type,
if (op2.singleton_p (&offset) && !integer_zerop (offset))
return range_op_handler (TRUNC_DIV_EXPR, type).fold_range (r, type,
lhs, op2);
+
+ // ~[0, 0] = op1 * op2 defines op1 and op2 as non-zero.
+ if (!contains_zero_p ((lhs)))
+ {
+ r.set_nonzero (type);
+ return true;
+ }
+
return false;
}
diff --git a/gcc/testsuite/gcc.dg/pr110992.c b/gcc/testsuite/gcc.dg/pr110992.c
new file mode 100644
index 00000000000..05e9b9267e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr110992.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void foo (int);
+
+int f(unsigned b, short c)
+{
+ int bt = b;
+ int bt1 = bt;
+ int t = bt1 & -(c!=0);
+ // int t = bt1 * (c!=0);
+
+ if (!t) return 0;
+ foo(bt == 0);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "foo \\(0\\)" 1 "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr119471.c b/gcc/testsuite/gcc.dg/pr119471.c
new file mode 100644
index 00000000000..4c55d85f77c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119471.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int fa(int a, int b)
+{
+ int c = a * b;
+ if (c != 0)
+ return (a != 0);
+ return 0;
+}
+int fb(int a, int b)
+{
+ int c = a * b;
+ if (c != 0)
+ return (b != 0);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "PHI <1" 2 "evrp" } } */
--
2.45.0
From 15f3ea2326f97bbde68420606a885e8d0f87b262 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Thu, 27 Mar 2025 13:44:00 -0400
Subject: [PATCH 1/3] If the LHS does not contain zero, neither do multiply
operands.
Given ~[0,0] = op1 * op2, range-ops should determine that neither op1 nor
op2 is zero. Add this to the operator_mult for op1_range. op2_range
simply invokes op1_range, so both will be covered.
PR tree-optimzation/110992.c
PR tree-optimzation/119471.c
gcc/
* range-op.cc (operator_mult::op1_range): If the LHS does not
contain zero, return non-zero.
gcc/testsuite/
* gcc.dg/pr110992.c: New.
* gcc.dg/pr119471.c: New.
---
gcc/range-op.cc | 7 +++++++
gcc/testsuite/gcc.dg/pr110992.c | 18 ++++++++++++++++++
gcc/testsuite/gcc.dg/pr119471.c | 19 +++++++++++++++++++
3 files changed, 44 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/pr110992.c
create mode 100644 gcc/testsuite/gcc.dg/pr119471.c
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index d1a1cd73687..6ea0d9935eb 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -2140,6 +2140,13 @@ operator_mult::op1_range (irange &r, tree type,
wide_int offset;
if (op2.singleton_p (offset) && offset != 0)
return range_op_handler (TRUNC_DIV_EXPR).fold_range (r, type, lhs, op2);
+
+ // ~[0, 0] = op1 * op2 defines op1 and op2 as non-zero.
+ if (!lhs.contains_p (wi::zero (TYPE_PRECISION (lhs.type ()))))
+ {
+ r.set_nonzero (type);
+ return true;
+ }
return false;
}
diff --git a/gcc/testsuite/gcc.dg/pr110992.c b/gcc/testsuite/gcc.dg/pr110992.c
new file mode 100644
index 00000000000..05e9b9267e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr110992.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void foo (int);
+
+int f(unsigned b, short c)
+{
+ int bt = b;
+ int bt1 = bt;
+ int t = bt1 & -(c!=0);
+ // int t = bt1 * (c!=0);
+
+ if (!t) return 0;
+ foo(bt == 0);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "foo \\(0\\)" 1 "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr119471.c b/gcc/testsuite/gcc.dg/pr119471.c
new file mode 100644
index 00000000000..4c55d85f77c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr119471.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int fa(int a, int b)
+{
+ int c = a * b;
+ if (c != 0)
+ return (a != 0);
+ return 0;
+}
+int fb(int a, int b)
+{
+ int c = a * b;
+ if (c != 0)
+ return (b != 0);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "PHI <1" 2 "evrp" } } */
--
2.45.0