Richard Biener <rguent...@suse.de> writes:
> The following fixes a problem with my last attempt of avoiding
> out-of-bound shift values for vectorized right shifts of widened
> operands.  Instead of truncating the shift amount with a bitwise
> and we actually need to saturate it to the target precision.
>
> The following does that and adds test coverage for the constant
> and invariant but variable case that would previously have failed.
>
> Bootstrap & regtest on x86_64-unknown-linux-gnu in progress, I plan
> to push this soon, just in case you have any comments here.

LGTM FWIW.

Richard

> Richard.
>
>       PR tree-optimization/110838
>       * tree-vect-patterns.cc (vect_recog_over_widening_pattern):
>       Fix right-shift value sanitizing.  Properly emit external
>       def mangling in the preheader rather than in the pattern
>       def sequence where it will fail vectorizing.
>
>       * gcc.dg/vect/pr110838.c: New testcase.
> ---
>  gcc/testsuite/gcc.dg/vect/pr110838.c | 31 ++++++++++++++++++++++++++++
>  gcc/tree-vect-patterns.cc            | 22 +++++++++++++++-----
>  2 files changed, 48 insertions(+), 5 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/vect/pr110838.c
>
> diff --git a/gcc/testsuite/gcc.dg/vect/pr110838.c 
> b/gcc/testsuite/gcc.dg/vect/pr110838.c
> new file mode 100644
> index 00000000000..cf8765be603
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/pr110838.c
> @@ -0,0 +1,31 @@
> +/* { dg-do run } */
> +
> +#include "tree-vect.h"
> +
> +short a[32], b[32];
> +
> +void __attribute__((noipa)) foo ()
> +{
> +  for (int i = 0; i < 32; ++i)
> +    a[i] = b[i] >> 16;
> +}
> +
> +void __attribute__((noipa)) bar (int n)
> +{
> +  int np = n & 31;
> +  for (int i = 0; i < 32; ++i)
> +    a[i] = b[i] >> np;
> +}
> +
> +int main ()
> +{
> +  check_vect ();
> +  b[0] = -8;
> +  foo ();
> +  if (a[0] != -1)
> +    abort ();
> +  bar (16);
> +  if (a[0] != -1)
> +    abort ();
> +  return 0;
> +}
> diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
> index e4ab8c2d65b..2cedf238450 100644
> --- a/gcc/tree-vect-patterns.cc
> +++ b/gcc/tree-vect-patterns.cc
> @@ -3109,8 +3109,8 @@ vect_recog_over_widening_pattern (vec_info *vinfo,
>        wide_int min_value, max_value;
>        if (TREE_CODE (ops[1]) == INTEGER_CST)
>       ops[1] = wide_int_to_tree (op_type,
> -                                wi::bit_and (wi::to_wide (ops[1]),
> -                                             new_precision - 1));
> +                                wi::umin (wi::to_wide (ops[1]),
> +                                          new_precision - 1));
>        else if (!vect_get_range_info (ops[1], &min_value, &max_value)
>              || wi::ge_p (max_value, new_precision, TYPE_SIGN (op_type)))
>       {
> @@ -3118,11 +3118,23 @@ vect_recog_over_widening_pattern (vec_info *vinfo,
>            same argument widened shifts and it un-CSEs same arguments.  */
>         tree new_var = vect_recog_temp_ssa_var (op_type, NULL);
>         gimple *pattern_stmt
> -         = gimple_build_assign (new_var, BIT_AND_EXPR, ops[1],
> +         = gimple_build_assign (new_var, MIN_EXPR, ops[1],
>                                  build_int_cst (op_type, new_precision - 1));
> -       ops[1] = new_var;
>         gimple_set_location (pattern_stmt, gimple_location (last_stmt));
> -       append_pattern_def_seq (vinfo, last_stmt_info, pattern_stmt);
> +       if (unprom[1].dt == vect_external_def)
> +         {
> +           if (edge e = vect_get_external_def_edge (vinfo, ops[1]))
> +             {
> +               basic_block new_bb
> +                 = gsi_insert_on_edge_immediate (e, pattern_stmt);
> +               gcc_assert (!new_bb);
> +             }
> +           else
> +             return NULL;
> +         }
> +       else
> +         append_pattern_def_seq (vinfo, last_stmt_info, pattern_stmt);
> +       ops[1] = new_var;
>       }
>      }

Reply via email to