aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-loop-manip.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vect-loop-manip.c')
-rw-r--r--gcc/tree-vect-loop-manip.c96
1 files changed, 89 insertions, 7 deletions
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 7cf00e6..2370b87 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -1084,6 +1084,33 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop *loop,
exit = single_exit (loop);
basic_block new_preheader = new_bbs[0];
+ /* Before installing PHI arguments make sure that the edges
+ into them match that of the scalar loop we analyzed. This
+ makes sure the SLP tree matches up between the main vectorized
+ loop and the epilogue vectorized copies. */
+ if (single_succ_edge (preheader)->dest_idx
+ != single_succ_edge (new_bbs[0])->dest_idx)
+ {
+ basic_block swap_bb = new_bbs[1];
+ gcc_assert (EDGE_COUNT (swap_bb->preds) == 2);
+ std::swap (EDGE_PRED (swap_bb, 0), EDGE_PRED (swap_bb, 1));
+ EDGE_PRED (swap_bb, 0)->dest_idx = 0;
+ EDGE_PRED (swap_bb, 1)->dest_idx = 1;
+ }
+ if (duplicate_outer_loop)
+ {
+ class loop *new_inner_loop = get_loop_copy (scalar_loop->inner);
+ if (loop_preheader_edge (scalar_loop)->dest_idx
+ != loop_preheader_edge (new_inner_loop)->dest_idx)
+ {
+ basic_block swap_bb = new_inner_loop->header;
+ gcc_assert (EDGE_COUNT (swap_bb->preds) == 2);
+ std::swap (EDGE_PRED (swap_bb, 0), EDGE_PRED (swap_bb, 1));
+ EDGE_PRED (swap_bb, 0)->dest_idx = 0;
+ EDGE_PRED (swap_bb, 1)->dest_idx = 1;
+ }
+ }
+
add_phi_args_after_copy (new_bbs, scalar_loop->num_nodes + 1, NULL);
/* Skip new preheader since it's deleted if copy loop is added at entry. */
@@ -2007,13 +2034,29 @@ vect_gen_vector_loop_niters (loop_vec_info loop_vinfo, tree niters,
niters_vector = force_gimple_operand (niters_vector, &stmts, true, var);
gsi_insert_seq_on_edge_immediate (pe, stmts);
/* Peeling algorithm guarantees that vector loop bound is at least ONE,
- we set range information to make niters analyzer's life easier. */
+ we set range information to make niters analyzer's life easier.
+ Note the number of latch iteration value can be TYPE_MAX_VALUE so
+ we have to represent the vector niter TYPE_MAX_VALUE + 1 >> log_vf. */
if (stmts != NULL && log_vf)
- set_range_info (niters_vector, VR_RANGE,
- wi::to_wide (build_int_cst (type, 1)),
- wi::to_wide (fold_build2 (RSHIFT_EXPR, type,
- TYPE_MAX_VALUE (type),
- log_vf)));
+ {
+ if (niters_no_overflow)
+ set_range_info (niters_vector, VR_RANGE,
+ wi::one (TYPE_PRECISION (type)),
+ wi::rshift (wi::max_value (TYPE_PRECISION (type),
+ TYPE_SIGN (type)),
+ exact_log2 (const_vf),
+ TYPE_SIGN (type)));
+ /* For VF == 1 the vector IV might also overflow so we cannot
+ assert a minimum value of 1. */
+ else if (const_vf > 1)
+ set_range_info (niters_vector, VR_RANGE,
+ wi::one (TYPE_PRECISION (type)),
+ wi::rshift (wi::max_value (TYPE_PRECISION (type),
+ TYPE_SIGN (type))
+ - (const_vf - 1),
+ exact_log2 (const_vf), TYPE_SIGN (type))
+ + 1);
+ }
}
*niters_vector_ptr = niters_vector;
*step_vector_ptr = step_vector;
@@ -2545,6 +2588,45 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
if (!prolog_peeling && !epilog_peeling)
return NULL;
+ /* Before doing any peeling make sure to reset debug binds outside of
+ the loop refering to defs not in LC SSA. */
+ class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ for (unsigned i = 0; i < loop->num_nodes; ++i)
+ {
+ basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i];
+ imm_use_iterator ui;
+ gimple *use_stmt;
+ for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, gimple_phi_result (gsi.phi ()))
+ if (gimple_debug_bind_p (use_stmt)
+ && loop != gimple_bb (use_stmt)->loop_father
+ && !flow_loop_nested_p (loop,
+ gimple_bb (use_stmt)->loop_father))
+ {
+ gimple_debug_bind_reset_value (use_stmt);
+ update_stmt (use_stmt);
+ }
+ }
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
+ gsi_next (&gsi))
+ {
+ ssa_op_iter op_iter;
+ def_operand_p def_p;
+ FOR_EACH_SSA_DEF_OPERAND (def_p, gsi_stmt (gsi), op_iter, SSA_OP_DEF)
+ FOR_EACH_IMM_USE_STMT (use_stmt, ui, DEF_FROM_PTR (def_p))
+ if (gimple_debug_bind_p (use_stmt)
+ && loop != gimple_bb (use_stmt)->loop_father
+ && !flow_loop_nested_p (loop,
+ gimple_bb (use_stmt)->loop_father))
+ {
+ gimple_debug_bind_reset_value (use_stmt);
+ update_stmt (use_stmt);
+ }
+ }
+ }
+
prob_vector = profile_probability::guessed_always ().apply_scale (9, 10);
estimated_vf = vect_vf_for_cost (loop_vinfo);
if (estimated_vf == 2)
@@ -2552,7 +2634,7 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
prob_prolog = prob_epilog = profile_probability::guessed_always ()
.apply_scale (estimated_vf - 1, estimated_vf);
- class loop *prolog, *epilog = NULL, *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ class loop *prolog, *epilog = NULL;
class loop *first_loop = loop;
bool irred_flag = loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP;