Fix `~X & X` and `~X | X` patterns
Checks
Commit Message
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.
---
gcc/match.pd | 6 +-
.../gcc.c-torture/execute/20230802-1.c | 68 +++++++++++++++++++
2 files changed, 72 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/gcc.c-torture/execute/20230802-1.c
@@ -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 */
new file mode 100644
@@ -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 ();
+ }
+}