On Mon, Apr 27, 2020 at 6:54 PM Richard Sandiford
<richard.sandif...@arm.com> wrote:
>
> Christophe Lyon <christophe.l...@linaro.org> writes:
> >> This PR was caused by mismatched expectations between
> >> vectorizable_comparison and SLP.  We had a "<" comparison
> >> between two booleans that were leaves of the SLP tree, so
> >> vectorizable_comparison fell back on:
> >>
> >>   /* Invariant comparison.  */
> >>   if (!vectype)
> >>     {
> >>       vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (rhs1),
> >>                                              slp_node);
> >>       if (maybe_ne (TYPE_VECTOR_SUBPARTS (vectype), nunits))
> >>         return false;
> >>     }
> >>
> >> rhs1 and rhs2 were *unsigned* boolean types, so we got back a vector
> >> of unsigned integers.  This in itself was OK, and meant that "<"
> >> worked as expected without the need for the boolean fix-ups:
> >>
> >>   /* Boolean values may have another representation in vectors
> >>      and therefore we prefer bit operations over comparison for
> >>      them (which also works for scalar masks).  We store opcodes
> >>      to use in bitop1 and bitop2.  Statement is vectorized as
> >>        BITOP2 (rhs1 BITOP1 rhs2) or
> >>        rhs1 BITOP2 (BITOP1 rhs2)
> >>      depending on bitop1 and bitop2 arity.  */
> >>   bool swap_p = false;
> >>   if (VECTOR_BOOLEAN_TYPE_P (vectype))
> >>     {
> >>
> >> However, vectorizable_comparison then used vect_get_slp_defs to get
> >> the actual operands.  The request went to vect_get_constant_vectors,
> >> which also has logic to calculate the vector type.  The problem was
> >> that this type was different from the one chosen above:
> >>
> >>   if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (op))
> >>       && vect_mask_constant_operand_p (stmt_vinfo))
> >>     vector_type = truth_type_for (stmt_vectype);
> >>   else
> >>     vector_type = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op), 
> >> op_node);
> >>
> >> So the function gave back a vector of mask types, which here are vectors
> >> of *signed* booleans.  This meant that "<" gave:
> >>
> >>   true (-1) < false (0)
> >>
> >> and so the boolean fixup above was needed after all.
> >>
> >> Fixed by making vectorizable_comparison also pick a mask type in this case.
> >>
> >> Tested on aarch64-linux-gnu (with and without SVE) and x86_64-linux-gnu.
> >> Approved by Richard in the PR.
> >>
> >> Richard
> >>
> >>
> >> 2020-04-23  Richard Sandiford  <richard.sandif...@arm.com>
> >>
> >> gcc/
> >>         PR tree-optimization/94727
> >>         * tree-vect-stmts.c (vectorizable_comparison): Use mask_type when
> >>         comparing invariant scalar booleans.
> >>
> >> gcc/testsuite/
> >>         PR tree-optimization/94727
> >>         * gcc.dg/vect/pr94727.c: New test.
> >
> > Hi Richard,
> >
> > The new testcase fails at execution on arm (and s390 according to
> > gcc-testresults).
> >
> > Can you check?
>
> Thanks for the heads-up.  Looks like we need the same fix when
> handling comparisons embedded in a VEC_COND_EXPR.
>
> Here too, the problem is that vect_get_constant_vectors will
> calculate its own vector type, using truth_type_for on the
> STMT_VINFO_VECTYPE, and the vectoriable_* routines need to be
> consistent with that.
>
> Tested on arm-linux-gnueabihf and x86_64-linux-gnu.  OK to install?

OK.

> Richard
>
>
> 2020-04-27  Richard Sandiford  <richard.sandif...@arm.com>
>
> gcc/
>         PR tree-optimization/94727
>         * tree-vect-stmts.c (vect_is_simple_cond): If both comparison
>         operands are invariant booleans, use the mask type associated with the
>         STMT_VINFO_VECTYPE.  Use !slp_node instead of !vectype to exclude SLP.
>         (vectorizable_condition): Pass vectype unconditionally to
>         vect_is_simple_cond.
> ---
>  gcc/tree-vect-stmts.c | 27 ++++++++++++++++-----------
>  1 file changed, 16 insertions(+), 11 deletions(-)
>
> diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
> index 88a1e2c51d2..1984787bac4 100644
> --- a/gcc/tree-vect-stmts.c
> +++ b/gcc/tree-vect-stmts.c
> @@ -9942,16 +9942,21 @@ vect_is_simple_cond (tree cond, vec_info *vinfo, 
> slp_tree slp_node,
>    if (! *comp_vectype)
>      {
>        tree scalar_type = TREE_TYPE (lhs);
> -      /* If we can widen the comparison to match vectype do so.  */
> -      if (INTEGRAL_TYPE_P (scalar_type)
> -         && vectype
> -         && tree_int_cst_lt (TYPE_SIZE (scalar_type),
> -                             TYPE_SIZE (TREE_TYPE (vectype))))
> -       scalar_type = build_nonstandard_integer_type
> -         (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (vectype))),
> -          TYPE_UNSIGNED (scalar_type));
> -      *comp_vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
> -                                                  slp_node);
> +      if (VECT_SCALAR_BOOLEAN_TYPE_P (scalar_type))
> +       *comp_vectype = truth_type_for (vectype);
> +      else
> +       {
> +         /* If we can widen the comparison to match vectype do so.  */
> +         if (INTEGRAL_TYPE_P (scalar_type)
> +             && !slp_node
> +             && tree_int_cst_lt (TYPE_SIZE (scalar_type),
> +                                 TYPE_SIZE (TREE_TYPE (vectype))))
> +           scalar_type = build_nonstandard_integer_type
> +             (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (vectype))),
> +              TYPE_UNSIGNED (scalar_type));
> +         *comp_vectype = get_vectype_for_scalar_type (vinfo, scalar_type,
> +                                                      slp_node);
> +       }
>      }
>
>    return true;
> @@ -10066,7 +10071,7 @@ vectorizable_condition (stmt_vec_info stmt_info, 
> gimple_stmt_iterator *gsi,
>    else_clause = gimple_assign_rhs3 (stmt);
>
>    if (!vect_is_simple_cond (cond_expr, stmt_info->vinfo, slp_node,
> -                           &comp_vectype, &dts[0], slp_node ? NULL : vectype)
> +                           &comp_vectype, &dts[0], vectype)
>        || !comp_vectype)
>      return false;
>
> --
> 2.17.1
>

Reply via email to