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

Reply via email to