This is an expansion of the optimize `a == CST & a`
to handle more than just casts. It adds optimization
for unary<a>.
The patch for binary operators will come later.
Bootstrapped and tested on x86_64-linux-gnu with no regressions.
PR tree-optimization/111487
gcc/ChangeLog:
* match.pd (tcc_int_unary): New operator list.
(`a == CST & unary(a)`): New pattern.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/and-unary-1.c: New test.
Signed-off-by: Andrew Pinski <[email protected]>
---
gcc/match.pd | 12 ++++
gcc/testsuite/gcc.dg/tree-ssa/and-unary-1.c | 61 +++++++++++++++++++++
2 files changed, 73 insertions(+)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/and-unary-1.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 07e743ae464..3ee28a3d8fc 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -57,6 +57,10 @@ along with GCC; see the file COPYING3. If not see
#include "cfn-operators.pd"
+/* integer unary operators that return the same type. */
+(define_operator_list tcc_int_unary
+ abs absu negate bit_not BSWAP POPCOUNT CTZ CLZ PARITY)
+
/* Define operand lists for math rounding functions {,i,l,ll}FN,
where the versions prefixed with "i" return an int, those prefixed with
"l" return a long and those prefixed with "ll" return a long long.
@@ -5451,6 +5455,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
@2
{ build_zero_cst (type); }))
+/* `(a == CST) & unary(a)` can be simplified to `(a == CST) & unary(CST)`. */
+(simplify
+ (bit_and:c (convert@2 (eq @0 INTEGER_CST@1))
+ (convert? (tcc_int_unary @3)))
+ (if (bitwise_equal_p (@0, @3))
+ (with { tree inner_type = TREE_TYPE (@3); }
+ (bit_and @2 (convert (tcc_int_unary (convert:inner_type @1)))))))
+
/* Optimize
# x_5 in range [cst1, cst2] where cst2 = cst1 + 1
x_5 == cstN ? cst4 : cst3
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/and-unary-1.c
b/gcc/testsuite/gcc.dg/tree-ssa/and-unary-1.c
new file mode 100644
index 00000000000..c157bc11b00
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/and-unary-1.c
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-forwprop1-raw -fdump-tree-optimized-raw" } */
+/* unary part of PR tree-optimization/111487 */
+
+int abs1(int a)
+{
+ int b = __builtin_abs(a);
+ return (a == 1) & b;
+}
+int absu1(int a)
+{
+ int b;
+ b = a > 0 ? -a:a;
+ b = -b;
+ return (a == 1) & b;
+}
+
+int bswap1(int a)
+{
+ int b = __builtin_bswap32(a);
+ return (a == 1) & b;
+}
+
+int ctz1(int a)
+{
+ int b = __builtin_ctz(a);
+ return (a == 1) & b;
+}
+int pop1(int a)
+{
+ int b = __builtin_popcount(a);
+ return (a == 1) & b;
+}
+int neg1(int a)
+{
+ int b = -(a);
+ return (a == 1) & b;
+}
+int not1(int a)
+{
+ int b = ~(a);
+ return (a == 1) & b;
+}
+int partity1(int a)
+{
+ int b = __builtin_parity(a);
+ return (a == 1) & b;
+}
+
+
+/* We should optimize out the unary operator for each.
+ For ctz we can optimize directly to `return 0`.
+ For bswap1 and not1, we can do the same but not until after forwprop1. */
+/* { dg-final { scan-tree-dump-times "eq_expr, " 7 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "eq_expr, " 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-not "abs_expr, " "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not "absu_expr, " "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not "bit_not_expr, " "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not "negate_expr, " "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not "gimple_call <" "forwprop1" } } */
+/* { dg-final { scan-tree-dump-not "bit_and_expr, " "forwprop1" } } */
--
2.34.1