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 diff --git a/gcc/match.pd b/gcc/match.pd index c62f205c13c..53e622bf28f 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 00000000000..8802ffa8238 --- /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 (); + } +} -- 2.31.1