aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Pinski <quic_apinski@quicinc.com>2024-06-11 17:16:42 -0700
committerAndrew Pinski <quic_apinski@quicinc.com>2024-06-12 08:44:49 -0700
commit0256121e2f23ac3550e87410c9b1e690c8edfc7c (patch)
tree65a1b68217abad9389c3faee421d221df2aeb1bc /gcc
parentbd6bc352d96304a13da63fed6aeb1615be535fd7 (diff)
downloadgcc-0256121e2f23ac3550e87410c9b1e690c8edfc7c.zip
gcc-0256121e2f23ac3550e87410c9b1e690c8edfc7c.tar.gz
gcc-0256121e2f23ac3550e87410c9b1e690c8edfc7c.tar.bz2
match: Improve gimple_bitwise_equal_p and gimple_bitwise_inverted_equal_p for truncating casts [PR115449]
As mentioned by Jeff in r15-831-g05daf617ea22e1d818295ed2d037456937e23530, we don't handle `(X | Y) & ~Y` -> `X & ~Y` on the gimple level when there are some different signed (but same precision) types dealing with matching `~Y` with the `Y` part. This improves both gimple_bitwise_equal_p and gimple_bitwise_inverted_equal_p to be able to say `(truncate)a` and `(truncate)a` are bitwise_equal and that `~(truncate)a` and `(truncate)a` are bitwise_invert_equal. Bootstrapped and tested on x86_64-linux-gnu with no regressions. PR tree-optimization/115449 gcc/ChangeLog: * gimple-match-head.cc (gimple_maybe_truncate): New declaration. (gimple_bitwise_equal_p): Match truncations that differ only in types with the same precision. (gimple_bitwise_inverted_equal_p): For matching after bit_not_with_nop call gimple_bitwise_equal_p. * match.pd (maybe_truncate): New match pattern. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/bitops-10.c: New test. Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gimple-match-head.cc17
-rw-r--r--gcc/match.pd7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c34
3 files changed, 48 insertions, 10 deletions
diff --git a/gcc/gimple-match-head.cc b/gcc/gimple-match-head.cc
index e26fa08..924d3f1 100644
--- a/gcc/gimple-match-head.cc
+++ b/gcc/gimple-match-head.cc
@@ -243,6 +243,7 @@ optimize_successive_divisions_p (tree divisor, tree inner_div)
gimple_bitwise_equal_p (expr1, expr2, valueize)
bool gimple_nop_convert (tree, tree *, tree (*) (tree));
+bool gimple_maybe_truncate (tree, tree *, tree (*) (tree));
/* Helper function for bitwise_equal_p macro. */
@@ -271,6 +272,10 @@ gimple_bitwise_equal_p (tree expr1, tree expr2, tree (*valueize) (tree))
}
if (expr2 != expr4 && operand_equal_p (expr1, expr4, 0))
return true;
+ if (gimple_maybe_truncate (expr3, &expr3, valueize)
+ && gimple_maybe_truncate (expr4, &expr4, valueize)
+ && operand_equal_p (expr3, expr4, 0))
+ return true;
return false;
}
@@ -318,21 +323,13 @@ gimple_bitwise_inverted_equal_p (tree expr1, tree expr2, bool &wascmp, tree (*va
/* Try if EXPR1 was defined as ~EXPR2. */
if (gimple_bit_not_with_nop (expr1, &other, valueize))
{
- if (operand_equal_p (other, expr2, 0))
- return true;
- tree expr4;
- if (gimple_nop_convert (expr2, &expr4, valueize)
- && operand_equal_p (other, expr4, 0))
+ if (gimple_bitwise_equal_p (other, expr2, valueize))
return true;
}
/* Try if EXPR2 was defined as ~EXPR1. */
if (gimple_bit_not_with_nop (expr2, &other, valueize))
{
- if (operand_equal_p (other, expr1, 0))
- return true;
- tree expr3;
- if (gimple_nop_convert (expr1, &expr3, valueize)
- && operand_equal_p (other, expr3, 0))
+ if (gimple_bitwise_equal_p (other, expr1, valueize))
return true;
}
diff --git a/gcc/match.pd b/gcc/match.pd
index 5cfe81e..3204cf4 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -200,6 +200,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(match (maybe_bit_not @0)
(bit_xor_cst@0 @1 @2))
+#if GIMPLE
+(match (maybe_truncate @0)
+ (convert @0)
+ (if (INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)))))
+#endif
+
/* Transform likes of (char) ABS_EXPR <(int) x> into (char) ABSU_EXPR <x>
ABSU_EXPR returns unsigned absolute value of the operand and the operand
of the ABSU_EXPR will have the corresponding signed type. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c b/gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c
new file mode 100644
index 0000000..000c5ae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/bitops-10.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized-raw" } */
+/* PR tree-optimization/115449 */
+
+void setBit_un(unsigned char *a, int b) {
+ unsigned char c = 0x1UL << b;
+ *a &= ~c;
+ *a |= c;
+}
+
+void setBit_sign(signed char *a, int b) {
+ signed char c = 0x1UL << b;
+ *a &= ~c;
+ *a |= c;
+}
+
+void setBit(char *a, int b) {
+ char c = 0x1UL << b;
+ *a &= ~c;
+ *a |= c;
+}
+/*
+ All three should produce:
+ _1 = 1 << b_4(D);
+ c_5 = (cast) _1;
+ _2 = *a_7(D);
+ _3 = _2 | c_5;
+ *a_7(D) = _3;
+ Removing the `&~c` as we are matching `(~x & y) | x` -> `x | y`
+ match pattern even with extra casts are being involved. */
+
+/* { dg-final { scan-tree-dump-not "bit_not_expr, " "optimized" } } */
+/* { dg-final { scan-tree-dump-not "bit_and_expr, " "optimized" } } */
+/* { dg-final { scan-tree-dump-times "bit_ior_expr, " 3 "optimized" } } */