On Wed, Aug 02, 2023 at 10:04:26AM +0200, Richard Biener via Gcc-patches wrote: > > --- a/gcc/match.pd > > +++ b/gcc/match.pd > > @@ -1157,8 +1157,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > > > /* Simplify ~X & X as zero. */ > > (simplify > > - (bit_and:c (convert? @0) (convert? (bit_not @0))) > > - { build_zero_cst (type); }) > > + (bit_and (convert? @0) (convert? @1)) > > + (if (bitwise_inverted_equal_p (@0, @1)) > > + { build_zero_cst (type); }))
I wonder if the above isn't incorrect. Without the possibility of widening converts it would be ok, but for widening conversions it is significant not just that the bits of @0 and @1 are inverted, but also that they are either both signed or both unsigned and so the MS bit (which is guaranteed to be different) extends to 0s in one case and to all 1s in the other one, so that even the upper bits are inverted. But that isn't the case here. Something like (untested): long long foo (unsigned int x) { int y = x; y = ~y; return ((long long) x) & y; } Actually maybe for this pattern it happens to be ok, because while the upper bits in this case might not be inverted between the extended operands (if x has msb set), it will be 0 & 0 in the upper bits. > > > > /* PR71636: Transform x & ((1U << b) - 1) -> x & ~(~0U << b); */ > > (simplify > > @@ -1395,8 +1396,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > /* ~x ^ x -> -1 */ > > (for op (bit_ior bit_xor) > > (simplify > > - (op:c (convert? @0) (convert? (bit_not @0))) > > - (convert { build_all_ones_cst (TREE_TYPE (@0)); }))) > > + (op (convert? @0) (convert? @1)) > > + (if (bitwise_inverted_equal_p (@0, @1)) > > + (convert { build_all_ones_cst (TREE_TYPE (@0)); })))) But not here. long long bar (unsigned int x) { int y = x; y = ~y; return ((long long) x) ^ y; } long long baz (unsigned int x) { int y = x; y = ~y; return y ^ ((long long) x); } You pick TREE_TYPE (@0), but that is a random signedness if the two operands have different signedness. Jakub