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?

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