diff options
Diffstat (limited to 'gcc/tree-vect-generic.c')
-rw-r--r-- | gcc/tree-vect-generic.c | 158 |
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); |