aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSam Feifer <sfeifer@redhat.com>2022-07-09 12:08:01 -0400
committerJeff Law <jeffreyalaw@gmail.com>2022-07-09 12:08:01 -0400
commitd9fa599dc7584d89e758a09a3d68982f12d8751c (patch)
treeff71ed921050fc43db5734a79c56ddbf972c6951 /gcc
parent46dc26fdfbf3e64f82188e21aa6a13ec23108e8e (diff)
downloadgcc-d9fa599dc7584d89e758a09a3d68982f12d8751c.zip
gcc-d9fa599dc7584d89e758a09a3d68982f12d8751c.tar.gz
gcc-d9fa599dc7584d89e758a09a3d68982f12d8751c.tar.bz2
[PATCH] match.pd: Add new bitwise arithmetic pattern [PR98304]
PR tree-optimization/98304 gcc: * match.pd (n - (((n > C1) ? n : C1) & -C2)): New simplification. gcc/testsuite: * gcc.c-torture/execute/pr98304-2.c: New test. * gcc.dg/pr98304-1.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/match.pd12
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr98304-2.c37
-rw-r--r--gcc/testsuite/gcc.dg/pr98304-1.c57
3 files changed, 106 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 6603f29..8bbc0db 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -8026,3 +8026,15 @@ and,
(match (bitwise_induction_p @0 @2 @3)
(bit_not
(nop_convert1? (bit_xor@0 (convert2? (lshift integer_onep@1 @2)) @3))))
+
+/* n - (((n > C1) ? n : C1) & -C2) -> n & C1 for unsigned case.
+ n - (((n > C1) ? n : C1) & -C2) -> (n <= C1) ? n : (n & C1) for signed case. */
+(simplify
+ (minus @0 (bit_and (max @0 INTEGER_CST@1) INTEGER_CST@2))
+ (with { auto i = wi::neg (wi::to_wide (@2)); }
+ /* Check if -C2 is a power of 2 and C1 = -C2 - 1. */
+ (if (wi::popcount (i) == 1
+ && (wi::to_wide (@1)) == (i - 1))
+ (if (TYPE_UNSIGNED (TREE_TYPE (@0)))
+ (bit_and @0 @1)
+ (cond (le @0 @1) @0 (bit_and @0 @1))))))
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr98304-2.c b/gcc/testsuite/gcc.c-torture/execute/pr98304-2.c
new file mode 100644
index 0000000..114c612
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr98304-2.c
@@ -0,0 +1,37 @@
+/* PR tree-optimization/98304 */
+
+#include "../../gcc.dg/pr98304-1.c"
+
+/* Runtime tests. */
+int main() {
+
+ /* Signed tests. */
+ if (foo(-42) != -42
+ || foo(0) != 0
+ || foo(63) != 63
+ || foo(64) != 0
+ || foo(65) != 1
+ || foo(99) != 35) {
+ __builtin_abort();
+ }
+
+ /* Unsigned tests. */
+ if (bar(42) != 42
+ || bar(0) != 0
+ || bar(63) != 63
+ || bar(64) != 0
+ || bar(65) != 1
+ || bar(99) != 35) {
+ __builtin_abort();
+ }
+
+ /* Should not simplify. */
+ if (corge(13) != 13
+ || thud(13) != 13
+ || qux(13) != 13
+ || quux(13) != 13) {
+ __builtin_abort();
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr98304-1.c b/gcc/testsuite/gcc.dg/pr98304-1.c
new file mode 100644
index 0000000..dce54dd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr98304-1.c
@@ -0,0 +1,57 @@
+/* PR tree-optimization/98304 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+/* Signed test function. */
+__attribute__((noipa)) int foo(int n) {
+ return n - (((n > 63) ? n : 63) & -64);
+}
+
+/* Unsigned test function. */
+__attribute__((noipa)) unsigned int bar(unsigned int n) {
+ return n - (((n > 63) ? n : 63) & -64);
+}
+
+/* Different power of 2. */
+__attribute__((noipa)) int goo(int n) {
+ return n - (((n > 31) ? n : 31) & -32);
+}
+
+/* Commutative property (should be identical to foo) */
+__attribute__((noipa)) int baz(int n) {
+ return n - (((64 > n) ? 63 : n) & -64);
+}
+
+/* < instead of >. */
+__attribute__((noipa)) int fred(int n) {
+ return n - (((63 < n) ? n : 63) & -64);
+}
+
+/* Constant is not a power of 2 so should not simplify. */
+__attribute__((noipa)) int qux(int n) {
+ return n - (((n > 62) ? n : 62) & -63);
+}
+
+/* Constant is not a power of 2 so should not simplify. */
+__attribute__((noipa)) unsigned int quux(unsigned int n) {
+ return n - (((n > 62) ? n : 62) & -63);
+}
+
+/* Constant is a variable so should not simplify. */
+__attribute__((noipa)) int waldo(int n, int x) {
+ return n - (((n > 63) ? n : 63) & x);
+}
+
+/* Difference between constants is not -1. */
+__attribute__((noipa)) int corge(int n) {
+ return n - (((n > 1) ? n : 1) & -64);
+}
+
+/* Difference between constants is not -1. */
+__attribute__((noipa)) unsigned int thud(unsigned int n)
+{
+ return n - (((n > 1) ? n : 1) & -64);
+}
+
+/* { dg-final { scan-tree-dump-times " - " 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times " <= " 4 "optimized" } } */