Jakub Jelinek <ja...@redhat.com> writes:
> Hi!
>
> Unlike x86, where the last operand of vector by scalar shift is DImode for
> V[248]DImode shifts, on aarch64 they seem to be SImode.
> vect_recog_rotate_pattern when the rotate amount is not constant casts the
> amount to the element type of the vector, so for V[248]DImode vectors to
> DImode, but then we ICE during expand_shift_1 because such argument doesn't
> satisfy the predicate and can't be widened to it.
>
> The following patch fixes it by special casing vector by scalar shifts
> when adding patterns for rotates, in that case we punt if the operand isn't
> INTEGER_CST or external_def, and the patch just keeps using the type of the
> amount operand the rotate had for the shifts too.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2019-12-10  Jakub Jelinek  <ja...@redhat.com>
>
>       PR target/92723
>       * tree-vect-patterns.c (vect_recog_rotate_pattern): If vector x vector
>       shifts aren't supported and rotate amount is SSA_NAME, use its type
>       rather than first operand's type for the shift amounts.
>
>       * gcc.dg/vect/pr92723.c: New test.
>
> --- gcc/tree-vect-patterns.c.jj       2019-12-09 11:12:29.983288823 +0100
> +++ gcc/tree-vect-patterns.c  2019-12-10 16:30:59.922177911 +0100
> @@ -2242,6 +2242,7 @@ vect_recog_rotate_pattern (stmt_vec_info
>    optab optab1, optab2;
>    edge ext_def = NULL;
>    bool bswap16_p = false;
> +  bool scalar_shift_p = false;
>  
>    if (is_gimple_assign (last_stmt))
>      {
> @@ -2420,6 +2421,7 @@ vect_recog_rotate_pattern (stmt_vec_info
>         || !optab2
>         || optab_handler (optab2, TYPE_MODE (vectype)) == CODE_FOR_nothing)
>       return NULL;
> +      scalar_shift_p = true;
>      }
>  
>    *type_out = vectype;
> @@ -2439,7 +2441,8 @@ vect_recog_rotate_pattern (stmt_vec_info
>    def = NULL_TREE;
>    scalar_int_mode mode = SCALAR_INT_TYPE_MODE (type);
>    if (TREE_CODE (oprnd1) == INTEGER_CST
> -      || TYPE_MODE (TREE_TYPE (oprnd1)) == mode)
> +      || TYPE_MODE (TREE_TYPE (oprnd1)) == mode
> +      || scalar_shift_p)
>      def = oprnd1;
>    else if (def_stmt && gimple_assign_cast_p (def_stmt))
>      {

WDYT about instead having:

  if (dt != vect_internal_def || TYPE_MODE (TREE_TYPE (oprnd1)) == mode)

and removing the ext_def stuff?  I'd have expected keeping the original
operand to always be best for vect_external_def, and it avoids changing
the function body during what's supposed to be just an analysis phase.

Thanks,
Richard

> --- gcc/testsuite/gcc.dg/vect/pr92723.c.jj    2019-12-10 16:37:09.924375698 
> +0100
> +++ gcc/testsuite/gcc.dg/vect/pr92723.c       2019-12-10 16:37:21.823189103 
> +0100
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +
> +void
> +foo (unsigned long long *x, unsigned long long *y, int z)
> +{
> +  int i;
> +  for (i = 0; i < 1024; i++)
> +    x[i] = (y[i] >> z) | (y[i] << (-z & (__SIZEOF_LONG_LONG__ * __CHAR_BIT__ 
> - 1)));
> +}
>
>       Jakub

Reply via email to