diff options
Diffstat (limited to 'gcc/tree-vect-loop.c')
-rw-r--r-- | gcc/tree-vect-loop.c | 319 |
1 files changed, 111 insertions, 208 deletions
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 5329982e..cc3d391 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -4485,7 +4485,6 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, = as_a <gphi *> (STMT_VINFO_REDUC_DEF (vect_orig_stmt (stmt_info))->stmt); enum tree_code code = STMT_VINFO_REDUC_CODE (reduc_info); internal_fn reduc_fn = STMT_VINFO_REDUC_FN (reduc_info); - stmt_vec_info prev_phi_info; tree vectype; machine_mode mode; class loop *loop = LOOP_VINFO_LOOP (loop_vinfo), *outer_loop = NULL; @@ -4493,7 +4492,6 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, tree scalar_dest; tree scalar_type; gimple *new_phi = NULL, *phi; - stmt_vec_info phi_info; gimple_stmt_iterator exit_gsi; tree new_temp = NULL_TREE, new_name, new_scalar_dest; gimple *epilog_stmt = NULL; @@ -4563,15 +4561,9 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, } else { + stmt_vec_info reduc_info = loop_vinfo->lookup_stmt (reduc_def_stmt); vec_num = 1; - ncopies = 0; - phi_info = STMT_VINFO_VEC_STMT (loop_vinfo->lookup_stmt (reduc_def_stmt)); - do - { - ncopies++; - phi_info = STMT_VINFO_RELATED_STMT (phi_info); - } - while (phi_info); + ncopies = STMT_VINFO_VEC_STMTS (reduc_info).length (); } /* For cond reductions we want to create a new vector (INDEX_COND_EXPR) @@ -4593,7 +4585,7 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, { if (gimple_assign_rhs_code (cond_info->stmt) == COND_EXPR) { - gimple *vec_stmt = STMT_VINFO_VEC_STMT (cond_info)->stmt; + gimple *vec_stmt = STMT_VINFO_VEC_STMTS (cond_info)[0]->stmt; gcc_assert (gimple_assign_rhs_code (vec_stmt) == VEC_COND_EXPR); ccompares.safe_push (std::make_pair (unshare_expr (gimple_assign_rhs1 (vec_stmt)), @@ -4714,29 +4706,27 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, if (double_reduc) loop = outer_loop; exit_bb = single_exit (loop)->dest; - prev_phi_info = NULL; new_phis.create (slp_node ? vec_num : ncopies); for (unsigned i = 0; i < vec_num; i++) { if (slp_node) def = vect_get_slp_vect_def (slp_node, i); else - def = gimple_get_lhs (STMT_VINFO_VEC_STMT (rdef_info)->stmt); + def = gimple_get_lhs (STMT_VINFO_VEC_STMTS (rdef_info)[0]->stmt); for (j = 0; j < ncopies; j++) { tree new_def = copy_ssa_name (def); phi = create_phi_node (new_def, exit_bb); - stmt_vec_info phi_info = loop_vinfo->add_stmt (phi); + loop_vinfo->add_stmt (phi); if (j == 0) new_phis.quick_push (phi); else { - def = vect_get_vec_def_for_stmt_copy (loop_vinfo, def); - STMT_VINFO_RELATED_STMT (prev_phi_info) = phi_info; + def = gimple_get_lhs (STMT_VINFO_VEC_STMTS (rdef_info)[j]->stmt); + new_phis.quick_push (phi); } SET_PHI_ARG_DEF (phi, single_exit (loop)->dest_idx, def); - prev_phi_info = phi_info; } } @@ -4807,15 +4797,12 @@ vect_create_epilog_for_reduction (loop_vec_info loop_vinfo, /* Likewise if we couldn't use a single defuse cycle. */ else if (ncopies > 1) { - gcc_assert (new_phis.length () == 1); gimple_seq stmts = NULL; tree first_vect = PHI_RESULT (new_phis[0]); first_vect = gimple_convert (&stmts, vectype, first_vect); - stmt_vec_info next_phi_info = loop_vinfo->lookup_stmt (new_phis[0]); for (int k = 1; k < ncopies; ++k) { - next_phi_info = STMT_VINFO_RELATED_STMT (next_phi_info); - tree second_vect = PHI_RESULT (next_phi_info->stmt); + tree second_vect = PHI_RESULT (new_phis[k]); second_vect = gimple_convert (&stmts, vectype, second_vect); first_vect = gimple_build (&stmts, code, vectype, first_vect, second_vect); @@ -5721,10 +5708,8 @@ vectorize_fold_left_reduction (loop_vec_info loop_vinfo, } else { - tree loop_vec_def0 = vect_get_vec_def_for_operand (loop_vinfo, - op0, stmt_info); - vec_oprnds0.create (1); - vec_oprnds0.quick_push (loop_vec_def0); + vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, 1, + op0, &vec_oprnds0); scalar_dest_def_info = stmt_info; } @@ -5814,7 +5799,10 @@ vectorize_fold_left_reduction (loop_vec_info loop_vinfo, } if (!slp_node) - STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info; + { + STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt_info); + *vec_stmt = new_stmt_info; + } return true; } @@ -6840,7 +6828,6 @@ vect_transform_reduction (loop_vec_info loop_vinfo, class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); int i; int ncopies; - int j; int vec_num; stmt_vec_info reduc_info = info_for_reduction (loop_vinfo, stmt_info); @@ -6897,7 +6884,6 @@ vect_transform_reduction (loop_vec_info loop_vinfo, /* Transform. */ stmt_vec_info new_stmt_info = NULL; - stmt_vec_info prev_stmt_info; tree new_temp = NULL_TREE; auto_vec<tree> vec_oprnds0; auto_vec<tree> vec_oprnds1; @@ -6932,139 +6918,83 @@ vect_transform_reduction (loop_vec_info loop_vinfo, tree scalar_dest = gimple_assign_lhs (stmt); tree vec_dest = vect_create_destination_var (scalar_dest, vectype_out); - prev_stmt_info = NULL; - if (!slp_node) + vect_get_vec_defs (loop_vinfo, stmt_info, slp_node, ncopies, + single_defuse_cycle && reduc_index == 0 + ? NULL_TREE : ops[0], &vec_oprnds0, + single_defuse_cycle && reduc_index == 1 + ? NULL_TREE : ops[1], &vec_oprnds1, + op_type == ternary_op + && !(single_defuse_cycle && reduc_index == 2) + ? ops[2] : NULL_TREE, &vec_oprnds2); + if (single_defuse_cycle) { - vec_oprnds0.create (1); - vec_oprnds1.create (1); - if (op_type == ternary_op) - vec_oprnds2.create (1); + gcc_assert (!slp_node); + vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, 1, + ops[reduc_index], + reduc_index == 0 ? &vec_oprnds0 + : (reduc_index == 1 ? &vec_oprnds1 + : &vec_oprnds2)); } - for (j = 0; j < ncopies; j++) + FOR_EACH_VEC_ELT (vec_oprnds0, i, def0) { - /* Handle uses. */ - if (j == 0) - { - if (slp_node) - { - /* Get vec defs for all the operands except the reduction index, - ensuring the ordering of the ops in the vector is kept. */ - auto_vec<vec<tree>, 3> vec_defs; - vect_get_slp_defs (loop_vinfo, slp_node, &vec_defs); - vec_oprnds0.safe_splice (vec_defs[0]); - vec_defs[0].release (); - vec_oprnds1.safe_splice (vec_defs[1]); - vec_defs[1].release (); - if (op_type == ternary_op) - { - vec_oprnds2.safe_splice (vec_defs[2]); - vec_defs[2].release (); - } - } - else + tree vop[3] = { def0, vec_oprnds1[i], NULL_TREE }; + if (masked_loop_p && !mask_by_cond_expr) + { + /* Make sure that the reduction accumulator is vop[0]. */ + if (reduc_index == 1) { - vec_oprnds0.quick_push - (vect_get_vec_def_for_operand (loop_vinfo, ops[0], stmt_info)); - vec_oprnds1.quick_push - (vect_get_vec_def_for_operand (loop_vinfo, ops[1], stmt_info)); - if (op_type == ternary_op) - vec_oprnds2.quick_push - (vect_get_vec_def_for_operand (loop_vinfo, ops[2], stmt_info)); + gcc_assert (commutative_tree_code (code)); + std::swap (vop[0], vop[1]); } - } + tree mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies, + vectype_in, i); + gcall *call = gimple_build_call_internal (cond_fn, 4, mask, + vop[0], vop[1], vop[0]); + new_temp = make_ssa_name (vec_dest, call); + gimple_call_set_lhs (call, new_temp); + gimple_call_set_nothrow (call, true); + new_stmt_info = vect_finish_stmt_generation (loop_vinfo, + stmt_info, call, gsi); + } else - { - if (!slp_node) - { - gcc_assert (reduc_index != -1 || ! single_defuse_cycle); - - if (single_defuse_cycle && reduc_index == 0) - vec_oprnds0[0] = gimple_get_lhs (new_stmt_info->stmt); - else - vec_oprnds0[0] - = vect_get_vec_def_for_stmt_copy (loop_vinfo, - vec_oprnds0[0]); - if (single_defuse_cycle && reduc_index == 1) - vec_oprnds1[0] = gimple_get_lhs (new_stmt_info->stmt); - else - vec_oprnds1[0] - = vect_get_vec_def_for_stmt_copy (loop_vinfo, - vec_oprnds1[0]); - if (op_type == ternary_op) - { - if (single_defuse_cycle && reduc_index == 2) - vec_oprnds2[0] = gimple_get_lhs (new_stmt_info->stmt); - else - vec_oprnds2[0] - = vect_get_vec_def_for_stmt_copy (loop_vinfo, - vec_oprnds2[0]); - } - } - } + { + if (op_type == ternary_op) + vop[2] = vec_oprnds2[i]; - FOR_EACH_VEC_ELT (vec_oprnds0, i, def0) - { - tree vop[3] = { def0, vec_oprnds1[i], NULL_TREE }; - if (masked_loop_p && !mask_by_cond_expr) + if (masked_loop_p && mask_by_cond_expr) { - /* Make sure that the reduction accumulator is vop[0]. */ - if (reduc_index == 1) - { - gcc_assert (commutative_tree_code (code)); - std::swap (vop[0], vop[1]); - } tree mask = vect_get_loop_mask (gsi, masks, vec_num * ncopies, - vectype_in, i * ncopies + j); - gcall *call = gimple_build_call_internal (cond_fn, 4, mask, - vop[0], vop[1], - vop[0]); - new_temp = make_ssa_name (vec_dest, call); - gimple_call_set_lhs (call, new_temp); - gimple_call_set_nothrow (call, true); - new_stmt_info - = vect_finish_stmt_generation (loop_vinfo, - stmt_info, call, gsi); - } - else - { - if (op_type == ternary_op) - vop[2] = vec_oprnds2[i]; - - if (masked_loop_p && mask_by_cond_expr) - { - tree mask = vect_get_loop_mask (gsi, masks, - vec_num * ncopies, - vectype_in, i * ncopies + j); - build_vect_cond_expr (code, vop, mask, gsi); - } - - gassign *new_stmt = gimple_build_assign (vec_dest, code, - vop[0], vop[1], vop[2]); - new_temp = make_ssa_name (vec_dest, new_stmt); - gimple_assign_set_lhs (new_stmt, new_temp); - new_stmt_info - = vect_finish_stmt_generation (loop_vinfo, - stmt_info, new_stmt, gsi); + vectype_in, i); + build_vect_cond_expr (code, vop, mask, gsi); } - if (slp_node) - SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info); - } - - if (slp_node || single_defuse_cycle) - continue; + gassign *new_stmt = gimple_build_assign (vec_dest, code, + vop[0], vop[1], vop[2]); + new_temp = make_ssa_name (vec_dest, new_stmt); + gimple_assign_set_lhs (new_stmt, new_temp); + new_stmt_info = vect_finish_stmt_generation (loop_vinfo, stmt_info, + new_stmt, gsi); + } - if (j == 0) - STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info; + if (slp_node) + SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info); + else if (single_defuse_cycle + && i < ncopies - 1) + { + if (reduc_index == 0) + vec_oprnds0.safe_push (gimple_get_lhs (new_stmt_info->stmt)); + else if (reduc_index == 1) + vec_oprnds1.safe_push (gimple_get_lhs (new_stmt_info->stmt)); + else if (reduc_index == 2) + vec_oprnds2.safe_push (gimple_get_lhs (new_stmt_info->stmt)); + } else - STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt_info; - - prev_stmt_info = new_stmt_info; + STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt_info); } - if (single_defuse_cycle && !slp_node) - STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt_info; + if (!slp_node) + *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0]; return true; } @@ -7080,7 +7010,6 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo, class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); int i; int ncopies; - stmt_vec_info prev_phi_info; int j; bool nested_cycle = false; int vec_num; @@ -7171,14 +7100,17 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo, STMT_VINFO_VEC_INDUC_COND_INITIAL_VAL (reduc_info) = NULL_TREE; } vec_initial_def = build_vector_from_val (vectype_out, induc_val); + vec_initial_defs.create (ncopies); + for (i = 0; i < ncopies; ++i) + vec_initial_defs.quick_push (vec_initial_def); } else if (nested_cycle) { /* Do not use an adjustment def as that case is not supported correctly if ncopies is not one. */ - vec_initial_def = vect_get_vec_def_for_operand (loop_vinfo, - initial_def, - reduc_stmt_info); + vect_get_vec_defs_for_operand (loop_vinfo, reduc_stmt_info, + ncopies, initial_def, + &vec_initial_defs); } else { @@ -7191,13 +7123,13 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo, = get_initial_def_for_reduction (loop_vinfo, reduc_stmt_info, code, initial_def, adjustment_defp); STMT_VINFO_REDUC_EPILOGUE_ADJUSTMENT (reduc_info) = adjustment_def; + vec_initial_defs.create (ncopies); + for (i = 0; i < ncopies; ++i) + vec_initial_defs.quick_push (vec_initial_def); } - vec_initial_defs.create (1); - vec_initial_defs.quick_push (vec_initial_def); } /* Generate the reduction PHIs upfront. */ - prev_phi_info = NULL; for (i = 0; i < vec_num; i++) { tree vec_init_def = vec_initial_defs[i]; @@ -7210,8 +7142,7 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo, /* Set the loop-entry arg of the reduction-phi. */ if (j != 0 && nested_cycle) - vec_init_def = vect_get_vec_def_for_stmt_copy (loop_vinfo, - vec_init_def); + vec_init_def = vec_initial_defs[j]; add_phi_arg (new_phi, vec_init_def, loop_preheader_edge (loop), UNKNOWN_LOCATION); @@ -7222,10 +7153,8 @@ vect_transform_cycle_phi (loop_vec_info loop_vinfo, else { if (j == 0) - STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_phi_info; - else - STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi_info; - prev_phi_info = new_phi_info; + *vec_stmt = new_phi_info; + STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_phi_info); } } } @@ -7260,43 +7189,23 @@ vectorizable_lc_phi (loop_vec_info loop_vinfo, basic_block bb = gimple_bb (stmt_info->stmt); edge e = single_pred_edge (bb); tree vec_dest = vect_create_destination_var (scalar_dest, vectype); - vec<tree> vec_oprnds = vNULL; - vect_get_vec_defs (loop_vinfo, - gimple_phi_arg_def (stmt_info->stmt, 0), NULL_TREE, - stmt_info, &vec_oprnds, NULL, slp_node); - if (slp_node) - { - unsigned vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node); - gcc_assert (vec_oprnds.length () == vec_num); - for (unsigned i = 0; i < vec_num; i++) - { - /* Create the vectorized LC PHI node. */ - gphi *new_phi = create_phi_node (vec_dest, bb); - add_phi_arg (new_phi, vec_oprnds[i], e, UNKNOWN_LOCATION); - stmt_vec_info new_phi_info = loop_vinfo->add_stmt (new_phi); - SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phi_info); - } - } - else - { - unsigned ncopies = vect_get_num_copies (loop_vinfo, vectype); - stmt_vec_info prev_phi_info = NULL; - for (unsigned i = 0; i < ncopies; i++) - { - if (i != 0) - vect_get_vec_defs_for_stmt_copy (loop_vinfo, &vec_oprnds, NULL); - /* Create the vectorized LC PHI node. */ - gphi *new_phi = create_phi_node (vec_dest, bb); - add_phi_arg (new_phi, vec_oprnds[0], e, UNKNOWN_LOCATION); - stmt_vec_info new_phi_info = loop_vinfo->add_stmt (new_phi); - if (i == 0) - STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_phi_info; - else - STMT_VINFO_RELATED_STMT (prev_phi_info) = new_phi_info; - prev_phi_info = new_phi_info; - } + auto_vec<tree> vec_oprnds; + vect_get_vec_defs (loop_vinfo, stmt_info, slp_node, + !slp_node ? vect_get_num_copies (loop_vinfo, vectype) : 1, + gimple_phi_arg_def (stmt_info->stmt, 0), &vec_oprnds); + for (unsigned i = 0; i < vec_oprnds.length (); i++) + { + /* Create the vectorized LC PHI node. */ + gphi *new_phi = create_phi_node (vec_dest, bb); + add_phi_arg (new_phi, vec_oprnds[i], e, UNKNOWN_LOCATION); + stmt_vec_info new_phi_info = loop_vinfo->add_stmt (new_phi); + if (slp_node) + SLP_TREE_VEC_STMTS (slp_node).quick_push (new_phi_info); + else + STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_phi_info); } - vec_oprnds.release (); + if (!slp_node) + *vec_stmt = STMT_VINFO_VEC_STMTS (stmt_info)[0]; return true; } @@ -7668,8 +7577,10 @@ vectorizable_induction (loop_vec_info loop_vinfo, /* iv_loop is nested in the loop to be vectorized. init_expr had already been created during vectorization of previous stmts. We obtain it from the STMT_VINFO_VEC_STMT of the defining stmt. */ - vec_init = vect_get_vec_def_for_operand (loop_vinfo, - init_expr, stmt_info); + auto_vec<tree> vec_inits; + vect_get_vec_defs_for_operand (loop_vinfo, stmt_info, 1, + init_expr, &vec_inits); + vec_init = vec_inits[0]; /* If the initial value is not of proper type, convert it. */ if (!useless_type_conversion_p (vectype, TREE_TYPE (vec_init))) { @@ -7807,7 +7718,8 @@ vectorizable_induction (loop_vec_info loop_vinfo, add_phi_arg (induction_phi, vec_def, loop_latch_edge (iv_loop), UNKNOWN_LOCATION); - STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = induction_phi_info; + STMT_VINFO_VEC_STMTS (stmt_info).safe_push (induction_phi_info); + *vec_stmt = induction_phi_info; /* In case that vectorization factor (VF) is bigger than the number of elements that we can fit in a vectype (nunits), we have to generate @@ -7818,7 +7730,6 @@ vectorizable_induction (loop_vec_info loop_vinfo, if (ncopies > 1) { gimple_seq seq = NULL; - stmt_vec_info prev_stmt_vinfo; /* FORNOW. This restriction should be relaxed. */ gcc_assert (!nested_in_vect_loop); @@ -7846,7 +7757,6 @@ vectorizable_induction (loop_vec_info loop_vinfo, new_vec, step_vectype, NULL); vec_def = induc_def; - prev_stmt_vinfo = induction_phi_info; for (i = 1; i < ncopies; i++) { /* vec_i = vec_prev + vec_step */ @@ -7859,8 +7769,7 @@ vectorizable_induction (loop_vec_info loop_vinfo, gsi_insert_seq_before (&si, stmts, GSI_SAME_STMT); new_stmt = SSA_NAME_DEF_STMT (vec_def); new_stmt_info = loop_vinfo->add_stmt (new_stmt); - STMT_VINFO_RELATED_STMT (prev_stmt_vinfo) = new_stmt_info; - prev_stmt_vinfo = new_stmt_info; + STMT_VINFO_VEC_STMTS (stmt_info).safe_push (new_stmt_info); } } @@ -8047,14 +7956,8 @@ vectorizable_live_operation (loop_vec_info loop_vinfo, } else { - enum vect_def_type dt = STMT_VINFO_DEF_TYPE (stmt_info); - vec_lhs = vect_get_vec_def_for_operand_1 (stmt_info, dt); - gcc_checking_assert (ncopies == 1 - || !LOOP_VINFO_FULLY_MASKED_P (loop_vinfo)); - /* For multiple copies, get the last copy. */ - for (int i = 1; i < ncopies; ++i) - vec_lhs = vect_get_vec_def_for_stmt_copy (loop_vinfo, vec_lhs); + vec_lhs = gimple_get_lhs (STMT_VINFO_VEC_STMTS (stmt_info).last ()->stmt); /* Get the last lane in the vector. */ bitstart = int_const_binop (MINUS_EXPR, vec_bitsize, bitsize); |