aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Pinski <apinski@marvell.com>2023-08-02 15:54:20 -0700
committerAndrew Pinski <apinski@marvell.com>2023-08-02 19:32:04 -0700
commitff36932e4d6638e475d5c343c3032728f9925d3f (patch)
treeedecd8aae1d6d6fd5d8e88777ee3d07bf67004fd
parent1b53748c61a8b6489ca9a56a25037131335d3cc6 (diff)
downloadgcc-ff36932e4d6638e475d5c343c3032728f9925d3f.zip
gcc-ff36932e4d6638e475d5c343c3032728f9925d3f.tar.gz
gcc-ff36932e4d6638e475d5c343c3032728f9925d3f.tar.bz2
Fix `~X & X` and `~X | X` patterns
As Jakub noticed in https://gcc.gnu.org/pipermail/gcc-patches/2023-August/626039.html what I did was not totally correct because sometimes chosing the wrong type. So to get back to what the original code but keeping around the use of bitwise_inverted_equal_p, we just need to check if the types of the two catupures are the same type. Also adds a testcase for the problem Jakub found. Committed as obvious after a bootstrap and test. gcc/ChangeLog: * match.pd (`~X & X`): Check that the types match. (`~x | x`, `~x ^ x`): Likewise. gcc/testsuite/ChangeLog: * gcc.c-torture/execute/20230802-1.c: New test.
-rw-r--r--gcc/match.pd6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20230802-1.c68
2 files changed, 72 insertions, 2 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index c62f205..53e622b 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -1158,7 +1158,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Simplify ~X & X as zero. */
(simplify
(bit_and (convert? @0) (convert? @1))
- (if (bitwise_inverted_equal_p (@0, @1))
+ (if (types_match (TREE_TYPE (@0), TREE_TYPE (@1))
+ && bitwise_inverted_equal_p (@0, @1))
{ build_zero_cst (type); }))
/* PR71636: Transform x & ((1U << b) - 1) -> x & ~(~0U << b); */
@@ -1397,7 +1398,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(for op (bit_ior bit_xor)
(simplify
(op (convert? @0) (convert? @1))
- (if (bitwise_inverted_equal_p (@0, @1))
+ (if (types_match (TREE_TYPE (@0), TREE_TYPE (@1))
+ && bitwise_inverted_equal_p (@0, @1))
(convert { build_all_ones_cst (TREE_TYPE (@0)); }))))
/* x ^ x -> 0 */
diff --git a/gcc/testsuite/gcc.c-torture/execute/20230802-1.c b/gcc/testsuite/gcc.c-torture/execute/20230802-1.c
new file mode 100644
index 0000000..8802ffa
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20230802-1.c
@@ -0,0 +1,68 @@
+/* We used to simplify these incorrectly. */
+__attribute__((noipa))
+long long
+foo (unsigned int x)
+{
+ int y = x;
+ y = ~y;
+ return ((long long) x) & y;
+}
+
+__attribute__((noipa))
+long long
+foo_v (volatile unsigned int x)
+{
+ volatile int y = x;
+ y = ~y;
+ return ((long long) x) & y;
+}
+
+__attribute__((noipa))
+long long
+bar (unsigned int x)
+{
+ int y = x;
+ y = ~y;
+ return ((long long) x) ^ y;
+}
+
+__attribute__((noipa))
+long long
+bar_v (volatile unsigned int x)
+{
+ volatile int y = x;
+ y = ~y;
+ return ((long long) x) ^ y;
+}
+
+__attribute__((noipa))
+long long
+baz (unsigned int x)
+{
+ int y = x;
+ y = ~y;
+ return y ^ ((long long) x);
+}
+
+__attribute__((noipa))
+long long
+baz_v (volatile unsigned int x)
+{
+ volatile int y = x;
+ y = ~y;
+ return y ^ ((long long) x);
+}
+
+
+int main()
+{
+ for(int t = -1; t <= 1; t++)
+ {
+ if (foo(t) != foo_v(t))
+ __builtin_abort ();
+ if (bar(t) != bar_v(t))
+ __builtin_abort ();
+ if (baz(t) != baz_v(t))
+ __builtin_abort ();
+ }
+}