Hi! The parity(~X) simpliciation to parity(X) is incorrect for types with odd element precision, in that case parity(~X) is equivalent to parity(X) ^ 1. The following patch fixes this.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/16.2? 2026-07-29 Jakub Jelinek <[email protected]> PR tree-optimization/126471 * match.pd (parity(~X) is parity(X)): Only optimize this way if element_precision is even, otherwise optimize into parity(X) ^ 1. * gcc.dg/bitint-139.c: New test. --- gcc/match.pd.jj 2026-07-28 21:02:47.836319557 +0200 +++ gcc/match.pd 2026-07-29 16:13:46.327108421 +0200 @@ -10777,10 +10777,12 @@ (define_operator_list SYNC_FETCH_AND_AND #endif /* PARITY simplifications. */ -/* parity(~X) is parity(X). */ +/* parity(~X) is parity(X) for even precision and parity(X) ^ 1 otherwise. */ (simplify (PARITY (bit_not @0)) - (PARITY @0)) + (if ((element_precision (TREE_TYPE (@0)) & 1) == 0) + (PARITY @0) + (bit_xor (PARITY:type @0) { build_one_cst (type); }))) /* parity(bswap(x)) is parity(x). */ (for parity (PARITY) --- gcc/testsuite/gcc.dg/bitint-139.c.jj 2026-07-29 16:01:03.344808633 +0200 +++ gcc/testsuite/gcc.dg/bitint-139.c 2026-07-29 16:15:17.521949013 +0200 @@ -0,0 +1,36 @@ +/* PR tree-optimization/126471 */ +/* { dg-do run { target bitint575 } } */ +/* { dg-options "-O2" } */ + +[[gnu::noipa]] int +foo (unsigned _BitInt(129) x) +{ + return __builtin_parityg (~x); +} + +[[gnu::noipa]] int +bar (unsigned _BitInt(7) x) +{ + return __builtin_parityg (~x); +} + +[[gnu::noipa]] int +baz (unsigned _BitInt(256) x) +{ + return __builtin_parityg (~x); +} + +int +main () +{ + if (foo (0) != 1 + || foo (~(unsigned _BitInt(129)) 0) != 0 + || foo (1) != 0 + || bar (0) != 1 + || bar (~(unsigned _BitInt(7)) 0) != 0 + || bar (1) != 0 + || baz (0) != 0 + || baz (~(unsigned _BitInt(256)) 0) != 0 + || baz (1) != 1) + __builtin_abort (); +} Jakub
