[PATCH] match.pd: Fix parity (X) ^ parity (Y) simplification [PR112719]

Richard Biener richard.guenther@gmail.com
Tue Nov 28 09:10:49 GMT 2023



> Am 28.11.2023 um 09:36 schrieb Jakub Jelinek <jakub@redhat.com>:
> 
> Hi!
> 
> When looking around, I've noticed we have a similar simplification
> for parity (with ^ rather than +).  Note, unlike the popcount one,
> this one doesn't check for INTEGRAL_TYPE_P (type) (which rules out
> vector simplification), so I've used the old handling for types_match and
> otherwise do it only for scalar argument types and handle different
> precision in there.
> 
> The testcase ICEs without the previous patch on the first function,
> but strangely not on the second which tests parity.  The reason
> is that in this case there is no wi::bit_and test like for popcount
> and for BITINT_TYPEs build_call_internal actually refuses to create it
> and thus the whole simplification fails.  While
> .{CLZ,CTZ,CLRSB,FFS,POPCOUNT,PARITY} ifns are direct optab ifns for
> normal integer and vector types (and thus it is desirable to punt if
> there is no supported optab for them), they have this large/huge _BitInt
> extension before bitint lowering, so the patch also adjusts
> build_call_internal to allow that case.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok

Richard 

> 2023-11-28  Jakub Jelinek  <jakub@redhat.com>
> 
>    PR tree-optimization/112719
>    * match.pd (parity(X)^parity(Y) -> parity(X^Y)): Handle case of
>    mismatched types.
>    * gimple-match-exports.cc (build_call_internal): Add special-case for
>    bit query ifns on large/huge BITINT_TYPE before bitint lowering.
> 
>    * gcc.dg/bitint-43.c: New test.
> 
> --- gcc/match.pd.jj    2023-11-27 10:43:54.857068074 +0100
> +++ gcc/match.pd    2023-11-27 12:02:29.372447640 +0100
> @@ -8873,7 +8873,14 @@ (define_operator_list SYNC_FETCH_AND_AND
> /* parity(X)^parity(Y) is parity(X^Y).  */
> (simplify
>   (bit_xor (PARITY:s @0) (PARITY:s @1))
> -  (PARITY (bit_xor @0 @1)))
> +  (if (types_match (TREE_TYPE (@0), TREE_TYPE (@1)))
> +   (PARITY (bit_xor @0 @1))
> +   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
> +    && INTEGRAL_TYPE_P (TREE_TYPE (@1)))
> +    (with { tree utype = TREE_TYPE (@0);
> +        if (TYPE_PRECISION (utype) < TYPE_PRECISION (TREE_TYPE (@1)))
> +          utype = TREE_TYPE (@1); }
> +     (PARITY (bit_xor (convert:utype @0) (convert:utype @1)))))))
> 
> #if GIMPLE
> /* parity(zext(X)) == parity(X).  */
> --- gcc/gimple-match-exports.cc.jj    2023-11-07 08:32:01.726254366 +0100
> +++ gcc/gimple-match-exports.cc    2023-11-27 12:31:06.273397492 +0100
> @@ -236,7 +236,30 @@ build_call_internal (internal_fn fn, gim
>       tree_pair types = direct_internal_fn_types (fn, res_op->type,
>                          res_op->ops);
>       if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
> -    return NULL;
> +    {
> +      switch (fn)
> +        {
> +        case IFN_CLZ:
> +        case IFN_CTZ:
> +        case IFN_CLRSB:
> +        case IFN_FFS:
> +        case IFN_POPCOUNT:
> +        case IFN_PARITY:
> +          /* For these 6 builtins large/huge _BitInt operand is ok
> +         before bitint lowering pass.  */
> +          if (res_op->num_ops >= 1
> +          && TREE_CODE (TREE_TYPE (res_op->ops[0])) == BITINT_TYPE
> +          && (TYPE_PRECISION (TREE_TYPE (res_op->ops[0]))
> +              > MAX_FIXED_MODE_SIZE)
> +          && cfun
> +          && (cfun->curr_properties & PROP_gimple_lbitint) == 0)
> +        break;
> +          return NULL;
> +
> +        default:
> +          return NULL;
> +        }
> +    }
>     }
>   return gimple_build_call_internal (fn, res_op->num_ops,
>                     res_op->op_or_null (0),
> --- gcc/testsuite/gcc.dg/bitint-43.c.jj    2023-11-27 12:32:18.043392501 +0100
> +++ gcc/testsuite/gcc.dg/bitint-43.c    2023-11-27 12:32:58.677823505 +0100
> @@ -0,0 +1,19 @@
> +/* PR tree-optimization/112719 */
> +/* { dg-do compile { target bitint } } */
> +/* { dg-options "-O2" } */
> +
> +#if __BITINT_MAXWIDTH__ >= 252
> +int
> +foo (unsigned _BitInt(239) x, unsigned _BitInt(252) y)
> +{
> +  x &= 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaauwb;
> +  y &= 0x555555555555555555555555555555555555555555555555555555555555555uwb;
> +  return __builtin_popcountg (x) + __builtin_popcountg (y);
> +}
> +
> +int
> +bar (unsigned _BitInt(239) x, unsigned _BitInt(252) y)
> +{
> +  return __builtin_parityg (x) ^ __builtin_parityg (y);
> +}
> +#endif
> 
>    Jakub
> 


More information about the Gcc-patches mailing list