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