> Am 18.12.2024 um 10:10 schrieb Jakub Jelinek <ja...@redhat.com>:
> 
> Hi!
> 
> The function comment says:
>   *XOR_P is to be FALSE if EXP might be a XOR used in a compare, in which
>   case, if XOR_CMP_OP is a zero constant, it will be overridden with *PEXP,
>   *XOR_P will be set to TRUE, and the left-hand operand of the XOR will be
>   decoded.  If *XOR_P is TRUE, XOR_CMP_OP is supposed to be NULL, and then the
>   right-hand operand of the XOR will be decoded.
> and the comment right above the xor_p handling says
>  /* Turn (a ^ b) [!]= 0 into a [!]= b.  */
> but I don't see anything that would actually check that the other operand is
> 0, in the testcase below it happily optimizes (a ^ 1) == 8 into a == 1.
> 
> The following patch adds that check.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

This is ok, please allow Alex to comment.

Richard 

> Note, there are various other parts of the function I'm worried about, but
> haven't had time to construct counterexamples yet.
> 
> One worrying thing is the
>  /* Drop casts, only save the outermost type.  We need not worry about
>     narrowing then widening casts, or vice-versa, for those that are not
>     essential for the compare have already been optimized out at this
>     point.  */
> comment, while obviously there are various optimizations which do optimize
> nested casts and the like, I'm not really sure it is safe to rely on them
> happening always before this optimization, there are various options to
> disable certain optimizations and some IL could appear right before
> ifcombine without being optimized yet the way this routine expects.
> Plus, the 3 casts are looked through in between various optimizations which
> might make those narrowing/widening or vice versa cases necessary.
> 
> Also, e.g. for the xor optimization, I think there is a difference between
> int a and
>  (a ^ 0x23) == 0
> and
>  ((int) (((unsigned char) a) ^ (unsigned char) 0x23)) == 0
> etc.
> 
> Another thing I'm worrying about are mixing up the different patterns
> together, there is the BIT_AND_EXPR handling, BIT_XOR_EXPR handling,
> RSHIFT_EXPR handling and then load handling.
> What if all 4 appear together, or 3 of them, 2 of them?
> Is the xor optimization still valid if there is BIT_AND_EXPR in between?
> I.e. instead of
>  (a ^ 123) == 0
> there is
>  ((a ^ 123) & 234) == 0
> ?

I was also worried during review about the very generic conversion stripping 
but it was said the fold-const code does the same.

> 2024-12-18  Jakub Jelinek  <ja...@redhat.com>
> 
>    PR tree-optimization/118081
>    * gimple-fold.cc (decode_field_reference): Only set *xor_p to true
>    if *xor_cmp_op is integer_zerop.
> 
>    * gcc.dg/pr118081.c: New test.
> 
> --- gcc/gimple-fold.cc.jj    2024-12-14 11:28:08.000000000 +0100
> +++ gcc/gimple-fold.cc    2024-12-17 17:27:31.294874825 +0100
> @@ -7572,7 +7572,7 @@ decode_field_reference (tree *pexp, HOST
>    /* Not much we can do when xor appears in the right-hand compare
>       operand.  */
>    return NULL_TREE;
> -      else
> +      else if (integer_zerop (*xor_cmp_op))
>    {
>      *xor_p = true;
>      exp = res_ops[0];
> --- gcc/testsuite/gcc.dg/pr118081.c.jj    2024-12-17 17:31:07.522860128 +0100
> +++ gcc/testsuite/gcc.dg/pr118081.c    2024-12-17 17:29:59.131813646 +0100
> @@ -0,0 +1,28 @@
> +/* PR tree-optimization/118081 */
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fno-tree-vrp -fno-expensive-optimizations" } */
> +
> +int a, b;
> +
> +int
> +foo (int f)
> +{
> +  return f ? f || 0 : f;
> +}
> +
> +void
> +bar (void)
> +{
> +  b = a ? a : 1;
> +  int i = foo (1 ^ b);
> +  signed char h = i - 8;
> +  if (h)
> +    return;
> +  __builtin_abort ();
> +}
> +
> +int
> +main ()
> +{
> +  bar ();
> +}
> 
>    Jakub
> 

Reply via email to