diff mbox series

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

Message ID ZWWmdfKznvpqZ2Ua@tucnak
State New
Headers show
Series match.pd: Fix parity (X) ^ parity (Y) simplification [PR112719] | expand

Commit Message

Jakub Jelinek Nov. 28, 2023, 8:36 a.m. UTC
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?

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.


	Jakub

Comments

Richard Biener Nov. 28, 2023, 9:10 a.m. UTC | #1
> 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
>
diff mbox series

Patch

--- 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