aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2023-10-25 09:46:50 -0400
committerAndrew MacLeod <amacleod@redhat.com>2023-11-03 12:54:50 -0400
commit7ab79a40b546a1470abaf76bec74c63e9990fe47 (patch)
tree6e109809952740cce8211058a0b44f70aea973c5 /gcc
parenta291237b628f419d7f7ac264dd7b42947b565222 (diff)
downloadgcc-7ab79a40b546a1470abaf76bec74c63e9990fe47.zip
gcc-7ab79a40b546a1470abaf76bec74c63e9990fe47.tar.gz
gcc-7ab79a40b546a1470abaf76bec74c63e9990fe47.tar.bz2
Adjust operators equal and not_equal to check bitmasks against constants
Check to see if a comparison to a constant can be determined to always be not-equal based on the bitmask. PR tree-optimization/111766 gcc/ * range-op.cc (operator_equal::fold_range): Check constants against the bitmask. (operator_not_equal::fold_range): Ditto. * value-range.h (irange_bitmask::member_p): New. gcc/testsuite/ * gcc.dg/pr111766.c: New.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/range-op.cc20
-rw-r--r--gcc/testsuite/gcc.dg/pr111766.c13
-rw-r--r--gcc/value-range.h14
3 files changed, 43 insertions, 4 deletions
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 33b193b..6137f2a 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -931,8 +931,9 @@ operator_equal::fold_range (irange &r, tree type,
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
- if (wi::eq_p (op1.lower_bound (), op1.upper_bound ())
- && wi::eq_p (op2.lower_bound (), op2.upper_bound ()))
+ bool op1_const = wi::eq_p (op1.lower_bound (), op1.upper_bound ());
+ bool op2_const = wi::eq_p (op2.lower_bound (), op2.upper_bound ());
+ if (op1_const && op2_const)
{
if (wi::eq_p (op1.lower_bound (), op2.upper_bound()))
r = range_true (type);
@@ -947,6 +948,11 @@ operator_equal::fold_range (irange &r, tree type,
tmp.intersect (op2);
if (tmp.undefined_p ())
r = range_false (type);
+ // Check if a constant cannot satisfy the bitmask requirements.
+ else if (op2_const && !op1.get_bitmask ().member_p (op2.lower_bound ()))
+ r = range_false (type);
+ else if (op1_const && !op2.get_bitmask ().member_p (op1.lower_bound ()))
+ r = range_false (type);
else
r = range_true_and_false (type);
}
@@ -1033,8 +1039,9 @@ operator_not_equal::fold_range (irange &r, tree type,
// We can be sure the values are always equal or not if both ranges
// consist of a single value, and then compare them.
- if (wi::eq_p (op1.lower_bound (), op1.upper_bound ())
- && wi::eq_p (op2.lower_bound (), op2.upper_bound ()))
+ bool op1_const = wi::eq_p (op1.lower_bound (), op1.upper_bound ());
+ bool op2_const = wi::eq_p (op2.lower_bound (), op2.upper_bound ());
+ if (op1_const && op2_const)
{
if (wi::ne_p (op1.lower_bound (), op2.upper_bound()))
r = range_true (type);
@@ -1049,6 +1056,11 @@ operator_not_equal::fold_range (irange &r, tree type,
tmp.intersect (op2);
if (tmp.undefined_p ())
r = range_true (type);
+ // Check if a constant cannot satisfy the bitmask requirements.
+ else if (op2_const && !op1.get_bitmask ().member_p (op2.lower_bound ()))
+ r = range_true (type);
+ else if (op1_const && !op2.get_bitmask ().member_p (op1.lower_bound ()))
+ r = range_true (type);
else
r = range_true_and_false (type);
}
diff --git a/gcc/testsuite/gcc.dg/pr111766.c b/gcc/testsuite/gcc.dg/pr111766.c
new file mode 100644
index 0000000..c27a029
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr111766.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+int
+foo3n(int c, int bb)
+{
+ if ((bb & ~3)!=0) __builtin_unreachable(); // bb = [0,3]
+ if ((bb & 1)==0) __builtin_unreachable(); // bb&1 == 0 // [0],[3]
+ if(bb == 2) __builtin_trap();
+ return bb;
+}
+
+/* { dg-final { scan-tree-dump-not "trap" "evrp" } } */
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 84f65ff..330e6f7 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -139,6 +139,7 @@ public:
void verify_mask () const;
void dump (FILE *) const;
+ bool member_p (const wide_int &val) const;
void adjust_range (irange &r) const;
// Convenience functions for nonzero bitmask compatibility.
@@ -202,6 +203,19 @@ irange_bitmask::set_nonzero_bits (const wide_int &bits)
verify_mask ();
}
+// Return TRUE if val could be a valid value with this bitmask.
+
+inline bool
+irange_bitmask::member_p (const wide_int &val) const
+{
+ if (unknown_p ())
+ return true;
+ wide_int res = m_mask & val;
+ if (m_value != 0)
+ res |= ~m_mask & m_value;
+ return res == val;
+}
+
inline bool
irange_bitmask::operator== (const irange_bitmask &src) const
{