The following fixes a latent issue where we use ranges to verify
correctness of a vector conversion optimization.  We rely on ranges
from 'op0' which for SLP is extracted from the representative stmt
which does not necessarily correspond to any actual scalar operation.
We also do not verify the range of all scalar lanes in the SLP
operand match.  The following rectifies this, restricting the support
to single-lane SLP nodes at this point - on branches we'd simply
not perform this optimization with SLP.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

        PR tree-optimization/115538
        * tree-vectorizer.h (vect_get_slp_scalar_def): Declare.
        * tree-vect-slp.cc (vect_get_slp_scalar_def): New helper.
        * tree-vect-generic.cc (expand_vector_conversion): Adjust.
        * tree-vect-stmts.cc (vectorizable_conversion): For SLP
        correctly look at ranges of the scalar defs of the SLP operand.
        (supportable_indirect_convert_operation): Likewise.
---
 gcc/tree-vect-generic.cc |  6 ++----
 gcc/tree-vect-slp.cc     | 19 +++++++++++++++++++
 gcc/tree-vect-stmts.cc   | 37 +++++++++++++++++++++++++++----------
 gcc/tree-vectorizer.h    |  4 +++-
 4 files changed, 51 insertions(+), 15 deletions(-)

diff --git a/gcc/tree-vect-generic.cc b/gcc/tree-vect-generic.cc
index c2f7a29d539..173ebd9a7ba 100644
--- a/gcc/tree-vect-generic.cc
+++ b/gcc/tree-vect-generic.cc
@@ -1755,10 +1755,8 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
     modifier = WIDEN;
 
   auto_vec<std::pair<tree, tree_code> > converts;
-  if (supportable_indirect_convert_operation (code,
-                                             ret_type, arg_type,
-                                             converts,
-                                             arg))
+  if (supportable_indirect_convert_operation (code, ret_type, arg_type,
+                                             converts))
     {
       new_rhs = arg;
       for (unsigned int i = 0; i < converts.length () - 1; i++)
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index ac1733004b6..8ed746ea5a9 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -10199,6 +10199,25 @@ vect_create_constant_vectors (vec_info *vinfo, 
slp_tree op_node)
       SLP_TREE_VEC_DEFS (op_node).quick_push (vop);
 }
 
+/* Get the scalar definition of the Nth lane from SLP_NODE or NULL_TREE
+   if there is no definition for it in the scalar IL or it is not known.  */
+
+tree
+vect_get_slp_scalar_def (slp_tree slp_node, unsigned n)
+{
+  if (SLP_TREE_DEF_TYPE (slp_node) == vect_internal_def)
+    {
+      if (!SLP_TREE_SCALAR_STMTS (slp_node).exists ())
+       return NULL_TREE;
+      stmt_vec_info def = SLP_TREE_SCALAR_STMTS (slp_node)[n];
+      if (!def)
+       return NULL_TREE;
+      return gimple_get_lhs (STMT_VINFO_STMT (def));
+    }
+  else
+    return SLP_TREE_SCALAR_OPS (slp_node)[n];
+}
+
 /* Get the Ith vectorized definition from SLP_NODE.  */
 
 tree
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index 1b639ae3b17..c815dd3a5b9 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -5610,10 +5610,8 @@ vectorizable_conversion (vec_info *vinfo,
        return false;
       gcc_assert (code.is_tree_code ());
       if (supportable_indirect_convert_operation (code,
-                                                 vectype_out,
-                                                 vectype_in,
-                                                 converts,
-                                                 op0))
+                                                 vectype_out, vectype_in,
+                                                 converts, op0, slp_op0))
        {
          gcc_assert (converts.length () <= 2);
          if (converts.length () == 1)
@@ -5750,7 +5748,16 @@ vectorizable_conversion (vec_info *vinfo,
       else if (code == FLOAT_EXPR)
        {
          wide_int op_min_value, op_max_value;
-         if (!vect_get_range_info (op0, &op_min_value, &op_max_value))
+         if (slp_node)
+           {
+             tree def;
+             /* ???  Merge ranges in case of more than one lane.  */
+             if (SLP_TREE_LANES (slp_op0) != 1
+                 || !(def = vect_get_slp_scalar_def (slp_op0, 0))
+                 || !vect_get_range_info (def, &op_min_value, &op_max_value))
+               goto unsupported;
+           }
+         else if (!vect_get_range_info (op0, &op_min_value, &op_max_value))
            goto unsupported;
 
          cvt_type
@@ -15197,7 +15204,7 @@ supportable_indirect_convert_operation (code_helper 
code,
                                        tree vectype_out,
                                        tree vectype_in,
                                        vec<std::pair<tree, tree_code> > 
&converts,
-                                       tree op0)
+                                       tree op0, slp_tree slp_op0)
 {
   bool found_mode = false;
   scalar_mode lhs_mode = GET_MODE_INNER (TYPE_MODE (vectype_out));
@@ -15269,10 +15276,20 @@ supportable_indirect_convert_operation (code_helper 
code,
                 In the future, if it is supported, changes may need to be made
                 to this part, such as checking the RANGE of each element
                 in the vector.  */
-             if (TREE_CODE (op0) != SSA_NAME
-                 || !SSA_NAME_RANGE_INFO (op0)
-                 || !vect_get_range_info (op0, &op_min_value,
-                                          &op_max_value))
+             if (slp_op0)
+               {
+                 tree def;
+                 /* ???  Merge ranges in case of more than one lane.  */
+                 if (SLP_TREE_LANES (slp_op0) != 1
+                     || !(def = vect_get_slp_scalar_def (slp_op0, 0))
+                     || !vect_get_range_info (def,
+                                              &op_min_value, &op_max_value))
+                   break;
+               }
+             else if (TREE_CODE (op0) != SSA_NAME
+                      || !SSA_NAME_RANGE_INFO (op0)
+                      || !vect_get_range_info (op0, &op_min_value,
+                                               &op_max_value))
                break;
 
              if (cvt_type == NULL_TREE
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 44d3a1d46c4..b0cb081cba0 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -2345,7 +2345,8 @@ extern bool supportable_narrowing_operation (code_helper, 
tree, tree,
 extern bool supportable_indirect_convert_operation (code_helper,
                                                    tree, tree,
                                                    vec<std::pair<tree, 
tree_code> > &,
-                                                   tree = NULL_TREE);
+                                                   tree = NULL_TREE,
+                                                   slp_tree = NULL);
 extern int compare_step_with_zero (vec_info *, stmt_vec_info);
 
 extern unsigned record_stmt_cost (stmt_vector_for_cost *, int,
@@ -2598,6 +2599,7 @@ extern bool vect_make_slp_decision (loop_vec_info);
 extern void vect_detect_hybrid_slp (loop_vec_info);
 extern void vect_optimize_slp (vec_info *);
 extern void vect_gather_slp_loads (vec_info *);
+extern tree vect_get_slp_scalar_def (slp_tree, unsigned);
 extern void vect_get_slp_defs (slp_tree, vec<tree> *);
 extern void vect_get_slp_defs (vec_info *, slp_tree, vec<vec<tree> > *,
                               unsigned n = -1U);
-- 
2.43.0

Reply via email to