aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/match.pd28
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/c-c++-common/fold-masked-cmp-3.c16
4 files changed, 52 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4567036..d1f54c0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,9 @@
2017-06-13 Yury Gribov <tetra2005@gmail.com>
+ * match.pd: New pattern.
+
+2017-06-13 Yury Gribov <tetra2005@gmail.com>
+
* tree-vrp.c (is_masked_range_test): New function.
(register_edge_assert_for): Determine ranges for
some bit tests.
diff --git a/gcc/match.pd b/gcc/match.pd
index 54a8e04..244e9eb 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2741,6 +2741,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
|| VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)))
{ constant_boolean_node (false, type); })))
+/* A & (2**N - 1) <= 2**K - 1 -> A & (2**N - 2**K) == 0
+ A & (2**N - 1) > 2**K - 1 -> A & (2**N - 2**K) != 0
+
+ Note that comparisons
+ A & (2**N - 1) < 2**K -> A & (2**N - 2**K) == 0
+ A & (2**N - 1) >= 2**K -> A & (2**N - 2**K) != 0
+ will be canonicalized to above so there's no need to
+ consider them here.
+ */
+
+(for cmp (le gt)
+ eqcmp (eq ne)
+ (simplify
+ (cmp (bit_and@0 @1 INTEGER_CST@2) INTEGER_CST@3)
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)))
+ (with
+ {
+ tree ty = TREE_TYPE (@0);
+ unsigned prec = TYPE_PRECISION (ty);
+ wide_int mask = wi::to_wide (@2, prec);
+ wide_int rhs = wi::to_wide (@3, prec);
+ signop sgn = TYPE_SIGN (ty);
+ }
+ (if ((mask & (mask + 1)) == 0 && wi::gt_p (rhs, 0, sgn)
+ && (rhs & (rhs + 1)) == 0 && wi::ge_p (mask, rhs, sgn))
+ (eqcmp (bit_and @1 { wide_int_to_tree (ty, mask - rhs); })
+ { build_zero_cst (ty); }))))))
+
/* -A CMP -B -> B CMP A. */
(for cmp (tcc_comparison)
scmp (swapped_tcc_comparison)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 678b892..71b89de 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2017-06-12 Yury Gribov <tetra2005@gmail.com>
+
+ * c-c++-common/fold-masked-cmp-3.c: New test.
+
2017-06-13 Yury Gribov <tetra2005@gmail.com>
PR tree-optimization/67328
diff --git a/gcc/testsuite/c-c++-common/fold-masked-cmp-3.c b/gcc/testsuite/c-c++-common/fold-masked-cmp-3.c
new file mode 100644
index 0000000..98900ec3
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fold-masked-cmp-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile { target x86_64-*-* } } */
+/* { dg-options "-fdump-tree-original" } */
+
+void foo (int *p, int x)
+{
+ if ((x & 0xff) <= 7)
+ *p = 0;
+}
+
+void bar (int *p, int x)
+{
+ if ((x & 0xff) < 8)
+ *p = 0;
+}
+
+/* { dg-final { scan-tree-dump-times "(x & .*) == 0" 2 "original" } } */