diff options
Diffstat (limited to 'gcc/tree-vect-generic.c')
-rw-r--r-- | gcc/tree-vect-generic.c | 173 |
1 files changed, 120 insertions, 53 deletions
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 8b00f32..6d5d651 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -40,10 +40,11 @@ along with GCC; see the file COPYING3. If not see #include "tree-vector-builder.h" #include "vec-perm-indices.h" #include "insn-config.h" +#include "tree-ssa-dce.h" #include "recog.h" /* FIXME: for insn_data */ -static void expand_vector_operations_1 (gimple_stmt_iterator *); +static void expand_vector_operations_1 (gimple_stmt_iterator *, bitmap); /* Return the number of elements in a vector type TYPE that we have already decided needs to be expanded piecewise. We don't support @@ -67,11 +68,10 @@ subparts_gt (tree type1, tree type2) } /* Build a constant of type TYPE, made of VALUE's bits replicated - every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */ + every WIDTH bits to fit TYPE's precision. */ static tree -build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value) +build_replicated_const (tree type, unsigned int width, HOST_WIDE_INT value) { - int width = tree_to_uhwi (TYPE_SIZE (inner_type)); int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT; unsigned HOST_WIDE_INT low, mask; @@ -214,13 +214,14 @@ do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b, tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED, enum tree_code code, tree type ATTRIBUTE_UNUSED) { + unsigned int width = vector_element_bits (TREE_TYPE (a)); tree inner_type = TREE_TYPE (TREE_TYPE (a)); unsigned HOST_WIDE_INT max; tree low_bits, high_bits, a_low, b_low, result_low, signs; max = GET_MODE_MASK (TYPE_MODE (inner_type)); - low_bits = build_replicated_const (word_type, inner_type, max >> 1); - high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1)); + low_bits = build_replicated_const (word_type, width, max >> 1); + high_bits = build_replicated_const (word_type, width, max & ~(max >> 1)); a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos); b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos); @@ -247,13 +248,14 @@ do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b, enum tree_code code ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED) { + unsigned int width = vector_element_bits (TREE_TYPE (b)); tree inner_type = TREE_TYPE (TREE_TYPE (b)); HOST_WIDE_INT max; tree low_bits, high_bits, b_low, result_low, signs; max = GET_MODE_MASK (TYPE_MODE (inner_type)); - low_bits = build_replicated_const (word_type, inner_type, max >> 1); - high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1)); + low_bits = build_replicated_const (word_type, width, max >> 1); + high_bits = build_replicated_const (word_type, width, max & ~(max >> 1)); b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos); @@ -276,8 +278,7 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f, tree part_width = TYPE_SIZE (inner_type); tree index = bitsize_int (0); int nunits = nunits_for_known_piecewise_op (type); - int delta = tree_to_uhwi (part_width) - / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type))); + int delta = tree_to_uhwi (part_width) / vector_element_bits (type); int i; location_t loc = gimple_location (gsi_stmt (*gsi)); @@ -357,8 +358,7 @@ expand_vector_addition (gimple_stmt_iterator *gsi, elem_op_func f, elem_op_func f_parallel, tree type, tree a, tree b, enum tree_code code) { - int parts_per_word = UNITS_PER_WORD - / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))); + int parts_per_word = BITS_PER_WORD / vector_element_bits (type); if (INTEGRAL_TYPE_P (TREE_TYPE (type)) && parts_per_word >= 4 @@ -371,17 +371,55 @@ expand_vector_addition (gimple_stmt_iterator *gsi, a, b, code); } +static bool +expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names); + /* Try to expand vector comparison expression OP0 CODE OP1 by querying optab if the following expression: VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}> can be expanded. */ static tree expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0, - tree op1, enum tree_code code) + tree op1, enum tree_code code, + bitmap dce_ssa_names) { + tree lhs = gimple_assign_lhs (gsi_stmt (*gsi)); + use_operand_p use_p; + imm_use_iterator iterator; + bool vec_cond_expr_only = true; + + /* As seen in PR95830, we should not expand comparisons that are only + feeding a VEC_COND_EXPR statement. */ + auto_vec<gimple *> uses; + FOR_EACH_IMM_USE_FAST (use_p, iterator, lhs) + uses.safe_push (USE_STMT (use_p)); + + for (unsigned i = 0; i < uses.length (); i ++) + { + gassign *use = dyn_cast<gassign *> (uses[i]); + if (use != NULL + && gimple_assign_rhs_code (use) == VEC_COND_EXPR + && gimple_assign_rhs1 (use) == lhs) + { + gimple_stmt_iterator it = gsi_for_stmt (use); + if (!expand_vector_condition (&it, dce_ssa_names)) + { + vec_cond_expr_only = false; + break; + } + } + else + { + vec_cond_expr_only = false; + break; + } + } + + if (!uses.is_empty () && vec_cond_expr_only) + return NULL_TREE; + tree t; - if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code) - && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code)) + if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)) { if (VECTOR_BOOLEAN_TYPE_P (type) && SCALAR_INT_MODE_P (TYPE_MODE (type)) @@ -391,7 +429,7 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0, (TREE_TYPE (type))))) { tree inner_type = TREE_TYPE (TREE_TYPE (op0)); - tree part_width = TYPE_SIZE (inner_type); + tree part_width = vector_element_bits_tree (TREE_TYPE (op0)); tree index = bitsize_int (0); int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0)); int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type)); @@ -695,12 +733,14 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, if (addend == NULL_TREE && expand_vec_cond_expr_p (type, type, LT_EXPR)) { - tree zero, cst, cond, mask_type; - gimple *stmt; + tree zero, cst, mask_type, mask; + gimple *stmt, *cond; mask_type = truth_type_for (type); zero = build_zero_cst (type); - cond = build2 (LT_EXPR, mask_type, op0, zero); + mask = make_ssa_name (mask_type); + cond = gimple_build_assign (mask, LT_EXPR, op0, zero); + gsi_insert_before (gsi, cond, GSI_SAME_STMT); tree_vector_builder vec (type, nunits, 1); for (i = 0; i < nunits; i++) vec.quick_push (build_int_cst (TREE_TYPE (type), @@ -708,8 +748,8 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, << shifts[i]) - 1)); cst = vec.build (); addend = make_ssa_name (type); - stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond, - cst, zero); + stmt + = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero); gsi_insert_before (gsi, stmt, GSI_SAME_STMT); } } @@ -930,8 +970,9 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, /* Expand a vector condition to scalars, by using many conditions on the vector's elements. */ -static void -expand_vector_condition (gimple_stmt_iterator *gsi) + +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); @@ -945,27 +986,36 @@ expand_vector_condition (gimple_stmt_iterator *gsi) vec<constructor_elt, va_gc> *v; tree constr; tree inner_type = TREE_TYPE (type); + tree width = vector_element_bits_tree (type); tree cond_type = TREE_TYPE (TREE_TYPE (a)); tree comp_inner_type = cond_type; - tree width = TYPE_SIZE (inner_type); tree index = bitsize_int (0); tree comp_width = width; tree comp_index = index; - int i; location_t loc = gimple_location (gsi_stmt (*gsi)); + tree_code code = TREE_CODE (a); + gassign *assign = NULL; - if (!is_gimple_val (a)) + if (code == SSA_NAME) { - gcc_assert (COMPARISON_CLASS_P (a)); - a_is_comparison = true; - a1 = TREE_OPERAND (a, 0); - a2 = TREE_OPERAND (a, 1); - comp_inner_type = TREE_TYPE (TREE_TYPE (a1)); - comp_width = TYPE_SIZE (comp_inner_type); + assign = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (a)); + if (assign != NULL + && TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison) + { + a_is_comparison = true; + a1 = gimple_assign_rhs1 (assign); + a2 = gimple_assign_rhs2 (assign); + code = gimple_assign_rhs_code (assign); + comp_inner_type = TREE_TYPE (TREE_TYPE (a1)); + comp_width = vector_element_bits_tree (TREE_TYPE (a1)); + } } - if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a))) - return; + if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), code)) + { + gcc_assert (TREE_CODE (a) == SSA_NAME || TREE_CODE (a) == VECTOR_CST); + return true; + } /* Handle vector boolean types with bitmasks. If there is a comparison and we can expand the comparison into the vector boolean bitmask, @@ -988,14 +1038,14 @@ expand_vector_condition (gimple_stmt_iterator *gsi) : expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a)))) { if (a_is_comparison) - a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2); + a = gimplify_build2 (gsi, code, type, a1, a2); a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b); a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a); a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c); a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2); gimple_assign_set_rhs_from_tree (gsi, a); update_stmt (gsi_stmt (*gsi)); - return; + return true; } /* TODO: try and find a smaller vector type. */ @@ -1019,7 +1069,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi) int nunits = nunits_for_known_piecewise_op (type); vec_alloc (v, nunits); - for (i = 0; i < nunits; i++) + for (int i = 0; i < nunits; i++) { tree aa, result; tree bb = tree_vec_extract (gsi, inner_type, b, width, index); @@ -1030,7 +1080,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi) comp_width, comp_index); tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, comp_width, comp_index); - aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2); + aa = fold_build2 (code, cond_type, aa1, aa2); } else if (a_is_scalar_bitmask) { @@ -1055,11 +1105,18 @@ expand_vector_condition (gimple_stmt_iterator *gsi) constr = build_constructor (type, v); gimple_assign_set_rhs_from_tree (gsi, constr); update_stmt (gsi_stmt (*gsi)); + + if (a_is_comparison) + bitmap_set_bit (dce_ssa_names, + SSA_NAME_VERSION (gimple_assign_lhs (assign))); + + return false; } static tree expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type, - gassign *assign, enum tree_code code) + gassign *assign, enum tree_code code, + bitmap dce_ssa_names) { machine_mode compute_mode = TYPE_MODE (compute_type); @@ -1113,7 +1170,8 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type tree rhs1 = gimple_assign_rhs1 (assign); tree rhs2 = gimple_assign_rhs2 (assign); - return expand_vector_comparison (gsi, type, rhs1, rhs2, code); + return expand_vector_comparison (gsi, type, rhs1, rhs2, code, + dce_ssa_names); } case TRUNC_DIV_EXPR: @@ -1334,7 +1392,7 @@ vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec) } else { - tree size = TYPE_SIZE (vect_elt_type); + tree size = vector_element_bits_tree (vect_type); tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index), size); return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos); @@ -1717,6 +1775,12 @@ expand_vector_conversion (gimple_stmt_iterator *gsi) gimple *stmt = gsi_stmt (*gsi); gimple *g; tree lhs = gimple_call_lhs (stmt); + if (lhs == NULL_TREE) + { + g = gimple_build_nop (); + gsi_replace (gsi, g, false); + return; + } tree arg = gimple_call_arg (stmt, 0); tree ret_type = TREE_TYPE (lhs); tree arg_type = TREE_TYPE (arg); @@ -1727,19 +1791,17 @@ expand_vector_conversion (gimple_stmt_iterator *gsi) optab optab1 = unknown_optab; gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type)); - gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (ret_type)))); - gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (arg_type)))); if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type)) && SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type))) code = FIX_TRUNC_EXPR; else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type)) && SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type))) code = FLOAT_EXPR; - if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type))) - < tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type)))) + unsigned int ret_elt_bits = vector_element_bits (ret_type); + unsigned int arg_elt_bits = vector_element_bits (arg_type); + if (ret_elt_bits < arg_elt_bits) modifier = NARROW; - else if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type))) - > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type)))) + else if (ret_elt_bits > arg_elt_bits) modifier = WIDEN; if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR)) @@ -1902,8 +1964,7 @@ expand_vector_conversion (gimple_stmt_iterator *gsi) tree part_width = TYPE_SIZE (compute_type); tree index = bitsize_int (0); int nunits = nunits_for_known_piecewise_op (arg_type); - int delta = tree_to_uhwi (part_width) - / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))); + int delta = tree_to_uhwi (part_width) / arg_elt_bits; int i; location_t loc = gimple_location (gsi_stmt (*gsi)); @@ -1950,7 +2011,8 @@ expand_vector_conversion (gimple_stmt_iterator *gsi) /* Process one statement. If we identify a vector operation, expand it. */ static void -expand_vector_operations_1 (gimple_stmt_iterator *gsi) +expand_vector_operations_1 (gimple_stmt_iterator *gsi, + bitmap dce_ssa_names) { tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE; enum tree_code code; @@ -1979,7 +2041,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) if (code == VEC_COND_EXPR) { - expand_vector_condition (gsi); + expand_vector_condition (gsi, dce_ssa_names); return; } @@ -2200,7 +2262,8 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) if (compute_type == type) return; - new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code); + new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code, + dce_ssa_names); /* Leave expression untouched for later expansion. */ if (new_rhs == NULL_TREE) @@ -2227,11 +2290,13 @@ expand_vector_operations (void) basic_block bb; bool cfg_changed = false; + auto_bitmap dce_ssa_names; + FOR_EACH_BB_FN (bb, cfun) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { - expand_vector_operations_1 (&gsi); + expand_vector_operations_1 (&gsi, dce_ssa_names); /* ??? If we do not cleanup EH then we will ICE in verification. But in reality we have created wrong-code as we did not properly transition EH info and edges to @@ -2242,6 +2307,8 @@ expand_vector_operations (void) } } + simple_dce_from_worklist (dce_ssa_names); + return cfg_changed ? TODO_cleanup_cfg : 0; } |