aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-generic.c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
committerIan Lance Taylor <iant@golang.org>2021-09-13 10:37:49 -0700
commite252b51ccde010cbd2a146485d8045103cd99533 (patch)
treee060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/tree-vect-generic.c
parentf10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff)
parent104c05c5284b7822d770ee51a7d91946c7e56d50 (diff)
downloadgcc-e252b51ccde010cbd2a146485d8045103cd99533.zip
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz
gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/tree-vect-generic.c')
-rw-r--r--gcc/tree-vect-generic.c158
1 files changed, 116 insertions, 42 deletions
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index c8d8493..0d7f041 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -41,9 +41,54 @@ along with GCC; see the file COPYING3. If not see
#include "vec-perm-indices.h"
#include "insn-config.h"
#include "tree-ssa-dce.h"
+#include "gimple-fold.h"
+#include "gimple-match.h"
#include "recog.h" /* FIXME: for insn_data */
+/* Build a ternary operation and gimplify it. Emit code before GSI.
+ Return the gimple_val holding the result. */
+
+static tree
+gimplify_build3 (gimple_stmt_iterator *gsi, enum tree_code code,
+ tree type, tree a, tree b, tree c)
+{
+ location_t loc = gimple_location (gsi_stmt (*gsi));
+ gimple_seq stmts = NULL;
+ tree ret = gimple_build (&stmts, loc, code, type, a, b, c);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ return ret;
+}
+
+/* Build a binary operation and gimplify it. Emit code before GSI.
+ Return the gimple_val holding the result. */
+
+static tree
+gimplify_build2 (gimple_stmt_iterator *gsi, enum tree_code code,
+ tree type, tree a, tree b)
+{
+ location_t loc = gimple_location (gsi_stmt (*gsi));
+ gimple_seq stmts = NULL;
+ tree ret = gimple_build (&stmts, loc, code, type, a, b);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ return ret;
+}
+
+/* Build a unary operation and gimplify it. Emit code before GSI.
+ Return the gimple_val holding the result. */
+
+static tree
+gimplify_build1 (gimple_stmt_iterator *gsi, enum tree_code code, tree type,
+ tree a)
+{
+ location_t loc = gimple_location (gsi_stmt (*gsi));
+ gimple_seq stmts = NULL;
+ tree ret = gimple_build (&stmts, loc, code, type, a);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ return ret;
+}
+
+
static void expand_vector_operations_1 (gimple_stmt_iterator *, bitmap);
/* Return the number of elements in a vector type TYPE that we have
@@ -122,23 +167,25 @@ typedef tree (*elem_op_func) (gimple_stmt_iterator *,
tree, tree, tree, tree, tree, enum tree_code,
tree);
+/* Extract the vector element of type TYPE at BITPOS with BITSIZE from T
+ and return it. */
+
tree
tree_vec_extract (gimple_stmt_iterator *gsi, tree type,
tree t, tree bitsize, tree bitpos)
{
- if (TREE_CODE (t) == SSA_NAME)
- {
- gimple *def_stmt = SSA_NAME_DEF_STMT (t);
- if (is_gimple_assign (def_stmt)
- && (gimple_assign_rhs_code (def_stmt) == VECTOR_CST
- || (bitpos
- && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR)))
- t = gimple_assign_rhs1 (def_stmt);
- }
- if (bitpos)
- return gimplify_build3 (gsi, BIT_FIELD_REF, type, t, bitsize, bitpos);
- else
- return gimplify_build1 (gsi, VIEW_CONVERT_EXPR, type, t);
+ /* We're using the resimplify API and maybe_push_res_to_seq to
+ simplify the BIT_FIELD_REF but restrict the simplification to
+ a single stmt while at the same time following SSA edges for
+ simplification with already emitted CTORs. */
+ gimple_match_op opr;
+ opr.set_op (BIT_FIELD_REF, type, t, bitsize, bitpos);
+ opr.resimplify (NULL, follow_all_ssa_edges);
+ gimple_seq stmts = NULL;
+ tree res = maybe_push_res_to_seq (&opr, &stmts);
+ gcc_assert (res);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ return res;
}
static tree
@@ -260,7 +307,7 @@ static tree
expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
tree type, tree inner_type,
tree a, tree b, enum tree_code code,
- tree ret_type = NULL_TREE)
+ bool parallel_p, tree ret_type = NULL_TREE)
{
vec<constructor_elt, va_gc> *v;
tree part_width = TYPE_SIZE (inner_type);
@@ -270,8 +317,7 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
int i;
location_t loc = gimple_location (gsi_stmt (*gsi));
- if (ret_type
- || types_compatible_p (gimple_expr_type (gsi_stmt (*gsi)), type))
+ if (ret_type || !parallel_p)
warning_at (loc, OPT_Wvector_operation_performance,
"vector operation will be expanded piecewise");
else
@@ -281,16 +327,22 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
if (!ret_type)
ret_type = type;
vec_alloc (v, (nunits + delta - 1) / delta);
+ bool constant_p = true;
for (i = 0; i < nunits;
i += delta, index = int_const_binop (PLUS_EXPR, index, part_width))
{
tree result = f (gsi, inner_type, a, b, index, part_width, code,
ret_type);
+ if (!CONSTANT_CLASS_P (result))
+ constant_p = false;
constructor_elt ce = {NULL_TREE, result};
v->quick_push (ce);
}
- return build_constructor (ret_type, v);
+ if (constant_p)
+ return build_vector_from_ctor (ret_type, v);
+ else
+ return build_constructor (ret_type, v);
}
/* Expand a vector operation to scalars with the freedom to use
@@ -311,13 +363,13 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
if (TYPE_MODE (TREE_TYPE (type)) == word_mode)
return expand_vector_piecewise (gsi, f,
type, TREE_TYPE (type),
- a, b, code);
+ a, b, code, true);
else if (n_words > 1)
{
tree word_type = build_word_mode_vector_type (n_words);
result = expand_vector_piecewise (gsi, f,
word_type, TREE_TYPE (word_type),
- a, b, code);
+ a, b, code, true);
result = force_gimple_operand_gsi (gsi, result, true, NULL, true,
GSI_SAME_STMT);
}
@@ -327,7 +379,8 @@ expand_vector_parallel (gimple_stmt_iterator *gsi, elem_op_func f, tree type,
scalar_int_mode mode
= int_mode_for_size (tree_to_uhwi (TYPE_SIZE (type)), 0).require ();
compute_type = lang_hooks.types.type_for_mode (mode, 1);
- result = f (gsi, compute_type, a, b, NULL_TREE, NULL_TREE, code, type);
+ result = f (gsi, compute_type, a, b, bitsize_zero_node,
+ TYPE_SIZE (compute_type), code, type);
warning_at (loc, OPT_Wvector_operation_performance,
"vector operation will be expanded with a "
"single scalar operation");
@@ -356,7 +409,7 @@ expand_vector_addition (gimple_stmt_iterator *gsi,
else
return expand_vector_piecewise (gsi, f,
type, TREE_TYPE (type),
- a, b, code);
+ a, b, code, false);
}
static bool
@@ -447,7 +500,7 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
else
t = expand_vector_piecewise (gsi, do_compare, type,
TREE_TYPE (TREE_TYPE (op0)), op0, op1,
- code);
+ code, false);
}
else
t = NULL_TREE;
@@ -963,7 +1016,7 @@ static bool
expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
{
gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
- tree type = gimple_expr_type (stmt);
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
tree a = gimple_assign_rhs1 (stmt);
tree a1 = a;
tree a2 = NULL_TREE;
@@ -1057,6 +1110,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
int nunits = nunits_for_known_piecewise_op (type);
vec_alloc (v, nunits);
+ bool constant_p = true;
for (int i = 0; i < nunits; i++)
{
tree aa, result;
@@ -1068,19 +1122,21 @@ expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
comp_width, comp_index);
tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
comp_width, comp_index);
- aa = fold_build2 (code, cond_type, aa1, aa2);
+ aa = build2 (code, cond_type, aa1, aa2);
}
else if (a_is_scalar_bitmask)
{
wide_int w = wi::set_bit_in_zero (i, TYPE_PRECISION (TREE_TYPE (a)));
result = gimplify_build2 (gsi, BIT_AND_EXPR, TREE_TYPE (a),
a, wide_int_to_tree (TREE_TYPE (a), w));
- aa = fold_build2 (NE_EXPR, boolean_type_node, result,
- build_zero_cst (TREE_TYPE (a)));
+ aa = build2 (NE_EXPR, boolean_type_node, result,
+ build_zero_cst (TREE_TYPE (a)));
}
else
aa = tree_vec_extract (gsi, cond_type, a, width, index);
result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc);
+ if (!CONSTANT_CLASS_P (result))
+ constant_p = false;
constructor_elt ce = {NULL_TREE, result};
v->quick_push (ce);
index = int_const_binop (PLUS_EXPR, index, width);
@@ -1090,7 +1146,10 @@ expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
comp_index = int_const_binop (PLUS_EXPR, comp_index, comp_width);
}
- constr = build_constructor (type, v);
+ if (constant_p)
+ constr = build_vector_from_ctor (type, v);
+ else
+ constr = build_constructor (type, v);
gimple_assign_set_rhs_from_tree (gsi, constr);
update_stmt (gsi_stmt (*gsi));
@@ -1188,11 +1247,11 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
if (TREE_CODE_CLASS (code) == tcc_unary)
return expand_vector_piecewise (gsi, do_unop, type, compute_type,
gimple_assign_rhs1 (assign),
- NULL_TREE, code);
+ NULL_TREE, code, false);
else
return expand_vector_piecewise (gsi, do_binop, type, compute_type,
gimple_assign_rhs1 (assign),
- gimple_assign_rhs2 (assign), code);
+ gimple_assign_rhs2 (assign), code, false);
}
/* Try to optimize
@@ -1515,7 +1574,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
elements + i - first)
: maybe_ge (poly_uint64 (indices[i]), elements))
break;
- if (i == elements)
+ if (first && i == elements)
{
gimple_assign_set_rhs3 (stmt, mask);
update_stmt (stmt);
@@ -1530,6 +1589,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
"vector shuffling operation will be expanded piecewise");
vec_alloc (v, elements);
+ bool constant_p = true;
for (i = 0; i < elements; i++)
{
si = size_int (i);
@@ -1591,10 +1651,15 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
t = v0_val;
}
+ if (!CONSTANT_CLASS_P (t))
+ constant_p = false;
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
}
- constr = build_constructor (vect_type, v);
+ if (constant_p)
+ constr = build_vector_from_ctor (vect_type, v);
+ else
+ constr = build_constructor (vect_type, v);
gimple_assign_set_rhs_from_tree (gsi, constr);
update_stmt (gsi_stmt (*gsi));
}
@@ -1679,11 +1744,11 @@ static void
expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
{
gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
- tree type = gimple_expr_type (stmt);
+ tree lhs = gimple_assign_lhs (stmt);
+ tree type = TREE_TYPE (lhs);
tree compute_type = get_compute_type (COND_EXPR, mov_optab, type);
machine_mode compute_mode = TYPE_MODE (compute_type);
gcc_assert (compute_mode != BLKmode);
- tree lhs = gimple_assign_lhs (stmt);
tree rhs2 = gimple_assign_rhs2 (stmt);
tree rhs3 = gimple_assign_rhs3 (stmt);
tree new_rhs;
@@ -1696,7 +1761,7 @@ expand_vector_scalar_condition (gimple_stmt_iterator *gsi)
COND_EXPR);
else
new_rhs = expand_vector_piecewise (gsi, do_cond, type, compute_type,
- rhs2, rhs3, COND_EXPR);
+ rhs2, rhs3, COND_EXPR, false);
if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
new_rhs);
@@ -1819,7 +1884,7 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
{
new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
ret_type, arg1_type, arg,
- NULL_TREE, code1);
+ NULL_TREE, code1, false);
g = gimple_build_assign (lhs, new_rhs);
gsi_replace (gsi, g, false);
return;
@@ -1887,7 +1952,7 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
do_vec_narrow_conversion,
arg_type, dcompute_type,
arg, NULL_TREE, code1,
- ret_type);
+ false, ret_type);
g = gimple_build_assign (lhs, new_rhs);
gsi_replace (gsi, g, false);
return;
@@ -1966,6 +2031,7 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
}
vec_alloc (v, (nunits + delta - 1) / delta * 2);
+ bool constant_p = true;
for (i = 0; i < nunits;
i += delta, index = int_const_binop (PLUS_EXPR, index,
part_width))
@@ -1976,12 +2042,19 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
index);
tree result = gimplify_build1 (gsi, code1, cretd_type, a);
constructor_elt ce = { NULL_TREE, result };
+ if (!CONSTANT_CLASS_P (ce.value))
+ constant_p = false;
v->quick_push (ce);
ce.value = gimplify_build1 (gsi, code2, cretd_type, a);
+ if (!CONSTANT_CLASS_P (ce.value))
+ constant_p = false;
v->quick_push (ce);
}
- new_rhs = build_constructor (ret_type, v);
+ if (constant_p)
+ new_rhs = build_vector_from_ctor (ret_type, v);
+ else
+ new_rhs = build_constructor (ret_type, v);
g = gimple_build_assign (lhs, new_rhs);
gsi_replace (gsi, g, false);
return;
@@ -1991,7 +2064,7 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
new_rhs = expand_vector_piecewise (gsi, do_vec_conversion, arg_type,
TREE_TYPE (arg_type), arg,
- NULL_TREE, code, ret_type);
+ NULL_TREE, code, false, ret_type);
g = gimple_build_assign (lhs, new_rhs);
gsi_replace (gsi, g, false);
}
@@ -2055,10 +2128,10 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi,
return;
rhs1 = gimple_assign_rhs1 (stmt);
- type = gimple_expr_type (stmt);
if (rhs_class == GIMPLE_BINARY_RHS)
rhs2 = gimple_assign_rhs2 (stmt);
+ type = TREE_TYPE (lhs);
if (!VECTOR_TYPE_P (type)
|| !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
return;
@@ -2089,9 +2162,10 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi,
if (op >= FIRST_NORM_OPTAB && op <= LAST_NORM_OPTAB
&& optab_handler (op, TYPE_MODE (TREE_TYPE (type))) != CODE_FOR_nothing)
{
- tree slhs = make_ssa_name (TREE_TYPE (TREE_TYPE (lhs)));
- gimple *repl = gimple_build_assign (slhs, code, srhs1, srhs2);
- gsi_insert_before (gsi, repl, GSI_SAME_STMT);
+ tree stype = TREE_TYPE (TREE_TYPE (lhs));
+ tree slhs = (rhs2 != NULL_TREE)
+ ? gimplify_build2 (gsi, code, stype, srhs1, srhs2)
+ : gimplify_build1 (gsi, code, stype, srhs1);
gimple_assign_set_rhs_from_tree (gsi,
build_vector_from_val (type, slhs));
update_stmt (stmt);