Message ID | ZWWmdfKznvpqZ2Ua@tucnak |
---|---|
State | New |
Headers | show |
Series | match.pd: Fix parity (X) ^ parity (Y) simplification [PR112719] | expand |
> 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 >
--- 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