From 553c6572061f6f9ef92514e8f13de95d509ad614 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Wed, 1 Jul 2020 14:44:07 -0600 Subject: [PATCH] match.pd: (x & y) - (x | y) - 1 -> ~(x ^ y) simplification [PR94882] gcc/ PR tree-optimization/94882 * match.pd (x & y) - (x | y) - 1 -> ~(x ^ y): New simplification. gcc/testsuite/ PR tree-optimization/94882 * gcc.dg/tree-ssa/pr94882.c: New test. * gcc.dg/tree-ssa/pr94882-1.c: New test. * gcc.dg/tree-ssa/pr94882-2.c: New test. * gcc.dg/tree-ssa/pr94882-3.c: New test. --- gcc/match.pd | 29 +++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c | 42 ++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c | 78 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c | 79 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/pr94882.c | 36 +++++++++++ 5 files changed, 264 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr94882.c diff --git a/gcc/match.pd b/gcc/match.pd index 43f3d7ab0fa..c6ae7a7db7a 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -1144,6 +1144,35 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (bit_xor (bit_ior:c (bit_not @0) @1) (bit_ior:c @0 (bit_not @1))) (bit_xor @0 @1)) +/* ((x & y) - (x | y)) - 1 -> ~(x ^ y) */ +(simplify + (plus (nop_convert1? (minus@2 (nop_convert2? (bit_and:c @0 @1)) + (nop_convert2? (bit_ior @0 @1)))) + integer_all_onesp) + (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type) + && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2)) + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2)) + && !TYPE_SATURATING (TREE_TYPE (@2))) + (bit_not (convert (bit_xor @0 @1))))) +(simplify + (minus (nop_convert1? (plus@2 (nop_convert2? (bit_and:c @0 @1)) + integer_all_onesp)) + (nop_convert3? (bit_ior @0 @1))) + (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type) + && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2)) + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2)) + && !TYPE_SATURATING (TREE_TYPE (@2))) + (bit_not (convert (bit_xor @0 @1))))) +(simplify + (minus (nop_convert1? (bit_and @0 @1)) + (nop_convert2? (plus@2 (nop_convert3? (bit_ior:c @0 @1)) + integer_onep))) + (if (!TYPE_OVERFLOW_SANITIZED (type) && !TYPE_OVERFLOW_TRAPS (type) + && !TYPE_SATURATING (type) && !TYPE_OVERFLOW_SANITIZED (TREE_TYPE (@2)) + && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (@2)) + && !TYPE_SATURATING (TREE_TYPE (@2))) + (bit_not (convert (bit_xor @0 @1))))) + /* ~x & ~y -> ~(x | y) ~x | ~y -> ~(x & y) */ (for op (bit_and bit_ior) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c new file mode 100644 index 00000000000..976b8e5bbdc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-1.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 4 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 4 "optimized" } } */ + +int +a (int x, int y) +{ + int t = x & y; + int tt = x | y; + t = t - tt; + return t + -1; +} + +int +b (int x, int y) +{ + int t = x & y; + int tt = x | y; + t = t - 1; + return t - tt; +} + +int +c (int x, int y) +{ + int t = x & y; + int tt = x | y; + tt = tt + 1; + return t - tt; +} + +int +d (int x, int y) +{ + int t = x & y; + int tt = x | y; + tt = tt + 1; + return t - tt; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c new file mode 100644 index 00000000000..7f533b6d468 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-2.c @@ -0,0 +1,78 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 8 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 8 "optimized" } } */ + +int +a (int x, int y) +{ + unsigned t = x & y; + unsigned tt = x | y; + t = t - tt; + return t + -1; +} + +int +a1 (int x, int y) +{ + int t = x & y; + int tt = x | y; + unsigned t1 = t - tt; + return t1 + -1; +} + +int +b (int x, int y) +{ + unsigned t = x & y; + unsigned tt = x | y; + t = t - 1; + return t - tt; +} + +int +b1 (int x, int y) +{ + int t = x & y; + int tt = x | y; + unsigned t1 = t - 1; + return t1 - tt; +} + +int +c (int x, int y) +{ + unsigned t = x & y; + unsigned tt = x | y; + tt = tt + 1; + return t - tt; +} + +int +c1 (int x, int y) +{ + int t = x & y; + int tt = x | y; + unsigned tt1 = tt + 1; + return t - tt1; +} + +int +d (int x, int y) +{ + unsigned t = x & y; + unsigned tt = x | y; + tt = tt + 1; + return t - tt; +} + +int +d1 (int x, int y) +{ + int t = x & y; + int tt = x | y; + unsigned tt1 = tt + 1; + return t - tt1; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c new file mode 100644 index 00000000000..979162f6a5a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94882-3.c @@ -0,0 +1,79 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 4 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "_\[0-9] \\^ _\[0-9]" 4 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 8 "optimized" } } */ + +signed char +a (short x, short y) +{ + unsigned char t = (unsigned char) (x & y); + unsigned char tt = (unsigned char) (x | y); + t = t - tt; + return (signed char) (t + -1); +} + +unsigned char +a1 (signed char x, signed char y) +{ + short t = (short) (x & y); + short tt = (short) (x | y); + unsigned char t1 = (unsigned char) (t - tt); + return t1 + -1; +} + +signed char +b (short x, short y) +{ + unsigned char t = (unsigned char) (x & y); + signed char tt = (signed char) (x | y); + t = t - 1; + return ((signed char) t - tt); +} + +short +b1 (short x, short y) +{ + int t = (int) (x & y); + int tt = (int) (x | y); + short t1 = (short) (t - 1); + return (short) (t1 - tt); +} + +signed char +c (unsigned x, unsigned y) +{ + unsigned char t = (unsigned char) (x & y); + signed char tt = (signed char) (x | y); + tt = tt + 1; + return (signed char) (t - tt); +} + +unsigned char +c1 (signed char x, signed char y) +{ + unsigned char t = (unsigned char) (x & y); + short tt = (short) (x | y); + unsigned char tt1 = (unsigned char) (tt + 1); + return t - tt1; +} + +signed char +d (unsigned char x, unsigned char y) +{ + int t = (int) (x & y); + int tt = (int) (x | y); + tt = tt + 1; + return (signed char) (t - tt); +} + +unsigned char +d1 (int x, int y) +{ + signed char t = (signed char) (x & y); + signed char tt = (signed char) (x | y); + unsigned char tt1 = (unsigned char) (tt + 1); + return (unsigned char) (t - tt1); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr94882.c b/gcc/testsuite/gcc.dg/tree-ssa/pr94882.c new file mode 100644 index 00000000000..e7a55308e85 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr94882.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) & y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "x_\[0-9]+\\\(D\\\) \\| y_\[0-9]+\\\(D\\\);" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "x_\[0-9]+\\\(D\\\) \\^ y_\[0-9]+\\\(D\\\);" 5 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "~_\[0-9]\+" 5 "optimized" } } */ + +int +a (int x, int y) +{ + return (x & y) - (x | y) - 1; +} + +int +b (int x, int y) +{ + return (x & y) - 1 - (x | y); +} + +int +c (int x, int y) +{ + return (x & y) - ((x | y) + 1); +} + +int +d (int x, int y) +{ + return (x & y) - (1 + (x | y)); +} + +int +e (int x, int y) +{ + return (unsigned) ((x & y) - (x | y)) + -1u; +} -- 2.30.2