[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