[gcc r16-665] Enhance bitwise_and::op1_range
Andrew Macleod
amacleod@gcc.gnu.org
Thu May 15 17:09:06 GMT 2025
https://gcc.gnu.org/g:ac55655ce45a237a6a01e0cce50211841603c2ec
commit r16-665-gac55655ce45a237a6a01e0cce50211841603c2ec
Author: Andrew MacLeod <amacleod@redhat.com>
Date: Wed May 14 11:32:58 2025 -0400
Enhance bitwise_and::op1_range
Any known bits from the LHS range can be used to specify known bits in
the non-mask operand.
PR tree-optimization/116546
gcc/
* range-op.cc (operator_bitwise_and::op1_range): Utilize bitmask
from the LHS to improve op1's bitmask.
gcc/testsuite/
* gcc.dg/pr116546.c: New.
Diff:
---
gcc/range-op.cc | 22 +++++++++++++++++++-
gcc/testsuite/gcc.dg/pr116546.c | 46 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 06d357f5199f..e2b9c82bc7b7 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -3716,14 +3716,34 @@ operator_bitwise_and::op1_range (irange &r, tree type,
return true;
}
+ if (!op2.singleton_p (mask))
+ return true;
+
// For 0 = op1 & MASK, op1 is ~MASK.
- if (lhs.zero_p () && op2.singleton_p ())
+ if (lhs.zero_p ())
{
wide_int nz = wi::bit_not (op2.get_nonzero_bits ());
int_range<2> tmp (type);
tmp.set_nonzero_bits (nz);
r.intersect (tmp);
}
+
+ irange_bitmask lhs_bm = lhs.get_bitmask ();
+ // given [5,7] mask 0x3 value 0x4 = N & [7, 7] mask 0x0 value 0x7
+ // Nothing is known about the bits not specified in the mask value (op2),
+ // Start with the mask, 1's will occur where values were masked.
+ wide_int op1_mask = ~mask;
+ // Any bits that are unknown on the LHS are also unknown in op1,
+ // so union the current mask with the LHS mask.
+ op1_mask |= lhs_bm.mask ();
+ // The resulting zeros correspond to known bits in the LHS mask, and
+ // the LHS value should tell us what they are. Mask off any
+ // extraneous values thats are not convered by the mask.
+ wide_int op1_value = lhs_bm.value () & ~op1_mask;
+ irange_bitmask op1_bm (op1_value, op1_mask);
+ // INtersect this mask with anything already known about the value.
+ op1_bm.intersect (r.get_bitmask ());
+ r.update_bitmask (op1_bm);
return true;
}
diff --git a/gcc/testsuite/gcc.dg/pr116546.c b/gcc/testsuite/gcc.dg/pr116546.c
new file mode 100644
index 000000000000..b82dc27f4522
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr116546.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+extern long foo (void);
+extern long bar (void);
+
+long
+test1 (long n)
+{
+ n &= 7;
+ if (n == 4) {
+ if (n & 4)
+ return foo ();
+ else
+ return bar ();
+ }
+ return 0;
+}
+
+long
+test2 (long n)
+{
+ n &= 7;
+ if (n > 4) {
+ if (n & 4)
+ return foo ();
+ else
+ return bar ();
+ }
+ return 0;
+}
+
+long
+test3 (long n)
+{
+ n &= 7;
+ if (n >= 4) {
+ if (n & 4)
+ return foo ();
+ else
+ return bar ();
+ }
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-not "bar" "evrp" } } */
More information about the Gcc-cvs
mailing list