diff mbox series

vect: Allow signed types in average fallback [PR89007]

Message ID 20260903055130.4059553-1-hongtao.liu@intel.com
State New
Headers show
Series vect: Allow signed types in average fallback [PR89007] | expand

Commit Message

Liu, Hongtao Sept. 3, 2026, 5:51 a.m. UTC
The average fallback is restricted to unsigned types, but it also works for
signed types.  Arithmetic right shifts round down, and the low-bit carry
adjusts the result in the same way.

Remove the unsigned restriction.  Use target_supports_op_p rather than
optab_for_tree_code to check whether the fallback operations are available.

Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
Ok for trunk?

gcc/ChangeLog:

	PR tree-optimization/89007
	* tree-vect-patterns.cc (vect_recog_average_pattern): Allow signed
	types in the fallback.  Check whether the fallback operations are
	supported.

gcc/testsuite/ChangeLog:

	PR tree-optimization/89007
	* gcc.target/i386/pr89007.c: New test.
---
 gcc/testsuite/gcc.target/i386/pr89007.c | 20 ++++++++++++++++++++
 gcc/tree-vect-patterns.cc               | 24 ++++++++++++------------
 2 files changed, 32 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr89007.c

Comments

Richard Biener Sept. 3, 2026, 7:28 a.m. UTC | #1
On Wed, 2 Sep 2026, liuhongt wrote:

> The average fallback is restricted to unsigned types, but it also works for
> signed types.  Arithmetic right shifts round down, and the low-bit carry
> adjusts the result in the same way.
> 
> Remove the unsigned restriction.  Use target_supports_op_p rather than
> optab_for_tree_code to check whether the fallback operations are available.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu{-m32,}.
> Ok for trunk?

OK.

Thanks,
Richard.

> gcc/ChangeLog:
> 
> 	PR tree-optimization/89007
> 	* tree-vect-patterns.cc (vect_recog_average_pattern): Allow signed
> 	types in the fallback.  Check whether the fallback operations are
> 	supported.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR tree-optimization/89007
> 	* gcc.target/i386/pr89007.c: New test.
> ---
>  gcc/testsuite/gcc.target/i386/pr89007.c | 20 ++++++++++++++++++++
>  gcc/tree-vect-patterns.cc               | 24 ++++++++++++------------
>  2 files changed, 32 insertions(+), 12 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/i386/pr89007.c
> 
> diff --git a/gcc/testsuite/gcc.target/i386/pr89007.c b/gcc/testsuite/gcc.target/i386/pr89007.c
> new file mode 100644
> index 00000000000..854fb54700a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr89007.c
> @@ -0,0 +1,20 @@
> +/* PR tree-optimization/89007 */
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -mavx512bw -mavx512vl -mprefer-vector-width=512" } */
> +
> +void
> +avg_floor (short *restrict d, short *restrict a, short *restrict b, int n)
> +{
> +  for (int i = 0; i < n; i++)
> +    d[i] = (a[i] + b[i]) >> 1;
> +}
> +
> +void
> +avg_ceil (short *restrict d, short *restrict a, short *restrict b, int n)
> +{
> +  for (int i = 0; i < n; i++)
> +    d[i] = (a[i] + b[i] + 1) >> 1;
> +}
> +
> +/* { dg-final { scan-assembler "vpsraw\[ \t\]" } } */
> +/* { dg-final { scan-assembler-not "vpsrad\[ \t\]" } } */
> diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
> index 406f81b95c8..15046a1cea9 100644
> --- a/gcc/tree-vect-patterns.cc
> +++ b/gcc/tree-vect-patterns.cc
> @@ -3581,17 +3581,15 @@ vect_recog_average_pattern (vec_info *vinfo,
>    if (!new_vectype)
>      return NULL;
>  
> -  bool fallback_p = false;
> -
> -  if (direct_internal_fn_supported_p (ifn, new_vectype, OPTIMIZE_FOR_SPEED))
> -    ;
> -  else if (TYPE_UNSIGNED (new_type)
> -	   && optab_for_tree_code (RSHIFT_EXPR, new_vectype, optab_scalar)
> -	   && optab_for_tree_code (PLUS_EXPR, new_vectype, optab_default)
> -	   && optab_for_tree_code (BIT_IOR_EXPR, new_vectype, optab_default)
> -	   && optab_for_tree_code (BIT_AND_EXPR, new_vectype, optab_default))
> -    fallback_p = true;
> -  else
> +  bool fallback_p = !direct_internal_fn_supported_p (ifn, new_vectype,
> +						      OPTIMIZE_FOR_SPEED);
> +  if (fallback_p
> +      && (!target_supports_op_p (new_vectype, RSHIFT_EXPR, optab_scalar)
> +	  || !target_supports_op_p (new_vectype, PLUS_EXPR, optab_default)
> +	  || !target_supports_op_p (new_vectype, BIT_AND_EXPR, optab_default)
> +	  || (ifn == IFN_AVG_CEIL
> +	      && !target_supports_op_p (new_vectype, BIT_IOR_EXPR,
> +					optab_default))))
>      return NULL;
>  
>    /* The IR requires a valid vector type for the cast result, even though
> @@ -3615,7 +3613,9 @@ vect_recog_average_pattern (vec_info *vinfo,
>  	 unmasked_carry = new_ops[0] and/or new_ops[1];
>  	 carry = unmasked_carry & 1;
>  	 new_var = sum_of_shifted + carry;
> -      */
> +
> +	 For signed types, arithmetic shifts round down and the carry is one
> +	 when both operands are odd (or either operand for IFN_AVG_CEIL).  */
>  
>        tree one_cst = build_one_cst (new_type);
>        gassign *g;
>
diff mbox series

Patch

diff --git a/gcc/testsuite/gcc.target/i386/pr89007.c b/gcc/testsuite/gcc.target/i386/pr89007.c
new file mode 100644
index 00000000000..854fb54700a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr89007.c
@@ -0,0 +1,20 @@ 
+/* PR tree-optimization/89007 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -mavx512bw -mavx512vl -mprefer-vector-width=512" } */
+
+void
+avg_floor (short *restrict d, short *restrict a, short *restrict b, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = (a[i] + b[i]) >> 1;
+}
+
+void
+avg_ceil (short *restrict d, short *restrict a, short *restrict b, int n)
+{
+  for (int i = 0; i < n; i++)
+    d[i] = (a[i] + b[i] + 1) >> 1;
+}
+
+/* { dg-final { scan-assembler "vpsraw\[ \t\]" } } */
+/* { dg-final { scan-assembler-not "vpsrad\[ \t\]" } } */
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index 406f81b95c8..15046a1cea9 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -3581,17 +3581,15 @@  vect_recog_average_pattern (vec_info *vinfo,
   if (!new_vectype)
     return NULL;
 
-  bool fallback_p = false;
-
-  if (direct_internal_fn_supported_p (ifn, new_vectype, OPTIMIZE_FOR_SPEED))
-    ;
-  else if (TYPE_UNSIGNED (new_type)
-	   && optab_for_tree_code (RSHIFT_EXPR, new_vectype, optab_scalar)
-	   && optab_for_tree_code (PLUS_EXPR, new_vectype, optab_default)
-	   && optab_for_tree_code (BIT_IOR_EXPR, new_vectype, optab_default)
-	   && optab_for_tree_code (BIT_AND_EXPR, new_vectype, optab_default))
-    fallback_p = true;
-  else
+  bool fallback_p = !direct_internal_fn_supported_p (ifn, new_vectype,
+						      OPTIMIZE_FOR_SPEED);
+  if (fallback_p
+      && (!target_supports_op_p (new_vectype, RSHIFT_EXPR, optab_scalar)
+	  || !target_supports_op_p (new_vectype, PLUS_EXPR, optab_default)
+	  || !target_supports_op_p (new_vectype, BIT_AND_EXPR, optab_default)
+	  || (ifn == IFN_AVG_CEIL
+	      && !target_supports_op_p (new_vectype, BIT_IOR_EXPR,
+					optab_default))))
     return NULL;
 
   /* The IR requires a valid vector type for the cast result, even though
@@ -3615,7 +3613,9 @@  vect_recog_average_pattern (vec_info *vinfo,
 	 unmasked_carry = new_ops[0] and/or new_ops[1];
 	 carry = unmasked_carry & 1;
 	 new_var = sum_of_shifted + carry;
-      */
+
+	 For signed types, arithmetic shifts round down and the carry is one
+	 when both operands are odd (or either operand for IFN_AVG_CEIL).  */
 
       tree one_cst = build_one_cst (new_type);
       gassign *g;