From 85bb2f9a302acc28dbae6c368d63680aacb15eb1 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 30 Jan 2018 11:19:47 +0000 Subject: [PATCH] re PR target/83008 ([performance] Is it better to avoid extra instructions in data passing between loops?) 2018-01-30 Richard Biener PR tree-optimization/83008 * tree-vect-slp.c (vect_analyze_slp_cost_1): Properly cost invariant and constant vector uses in stmts when they need more than one stmt. From-SVN: r257181 --- gcc/ChangeLog | 7 ++++++ gcc/tree-vect-slp.c | 56 +++++++++++++++++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eca095027fd..7be83e9930d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-01-30 Richard Biener + + PR tree-optimization/83008 + * tree-vect-slp.c (vect_analyze_slp_cost_1): Properly cost + invariant and constant vector uses in stmts when they need + more than one stmt. + 2018-01-30 Rainer Orth PR bootstrap/84017 diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 7fae17b340d..ca28632d6ba 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -1911,18 +1911,56 @@ vect_analyze_slp_cost_1 (slp_instance instance, slp_tree node, enum vect_def_type dt; if (!op || op == lhs) continue; - if (vect_is_simple_use (op, stmt_info->vinfo, &def_stmt, &dt)) + if (vect_is_simple_use (op, stmt_info->vinfo, &def_stmt, &dt) + && (dt == vect_constant_def || dt == vect_external_def)) { /* Without looking at the actual initializer a vector of constants can be implemented as load from the constant pool. - ??? We need to pass down stmt_info for a vector type - even if it points to the wrong stmt. */ - if (dt == vect_constant_def) - record_stmt_cost (prologue_cost_vec, 1, vector_load, - stmt_info, 0, vect_prologue); - else if (dt == vect_external_def) - record_stmt_cost (prologue_cost_vec, 1, vec_construct, - stmt_info, 0, vect_prologue); + When all elements are the same we can use a splat. */ + tree vectype = get_vectype_for_scalar_type (TREE_TYPE (op)); + unsigned group_size = SLP_TREE_SCALAR_STMTS (node).length (); + unsigned num_vects_to_check; + unsigned HOST_WIDE_INT const_nunits; + unsigned nelt_limit; + if (TYPE_VECTOR_SUBPARTS (vectype).is_constant (&const_nunits) + && ! multiple_p (const_nunits, group_size)) + { + num_vects_to_check = SLP_TREE_NUMBER_OF_VEC_STMTS (node); + nelt_limit = const_nunits; + } + else + { + /* If either the vector has variable length or the vectors + are composed of repeated whole groups we only need to + cost construction once. All vectors will be the same. */ + num_vects_to_check = 1; + nelt_limit = group_size; + } + tree elt = NULL_TREE; + unsigned nelt = 0; + for (unsigned j = 0; j < num_vects_to_check * nelt_limit; ++j) + { + unsigned si = j % group_size; + if (nelt == 0) + elt = gimple_op (SLP_TREE_SCALAR_STMTS (node)[si], i); + /* ??? We're just tracking whether all operands of a single + vector initializer are the same, ideally we'd check if + we emitted the same one already. */ + else if (elt != gimple_op (SLP_TREE_SCALAR_STMTS (node)[si], i)) + elt = NULL_TREE; + nelt++; + if (nelt == nelt_limit) + { + /* ??? We need to pass down stmt_info for a vector type + even if it points to the wrong stmt. */ + record_stmt_cost (prologue_cost_vec, 1, + dt == vect_external_def + ? (elt ? scalar_to_vec : vec_construct) + : vector_load, + stmt_info, 0, vect_prologue); + nelt = 0; + } + } } } -- 2.30.2