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

Reply via email to