aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vectorizer.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vectorizer.c')
-rw-r--r--gcc/tree-vectorizer.c121
1 files changed, 31 insertions, 90 deletions
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 0b3796f..a7cc59b 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -165,7 +165,7 @@ static struct loop *slpeel_tree_duplicate_loop_to_edge_cfg
static void slpeel_update_phis_for_duplicate_loop
(struct loop *, struct loop *, bool after);
static void slpeel_update_phi_nodes_for_guard (edge, struct loop *);
-static void slpeel_make_loop_iterate_ntimes (struct loop *, tree, tree, tree);
+static void slpeel_make_loop_iterate_ntimes (struct loop *, tree);
static edge slpeel_add_loop_guard (basic_block, tree, basic_block);
static bool slpeel_can_duplicate_loop_p (struct loop *, edge);
static void allocate_new_names (bitmap);
@@ -251,12 +251,11 @@ static void vect_generate_tmps_on_preheader
static tree vect_build_loop_niters (loop_vec_info);
static void vect_update_ivs_after_vectorizer (struct loop *, tree);
static tree vect_gen_niters_for_prolog_loop (loop_vec_info, tree);
-static void vect_update_niters_after_peeling (loop_vec_info, tree);
static void vect_update_inits_of_dr
(struct data_reference *, struct loop *, tree niters);
static void vect_update_inits_of_drs (loop_vec_info, tree);
static void vect_do_peeling_for_alignment (loop_vec_info, struct loops *);
-static void vect_transform_for_unknown_loop_bound
+static void vect_do_peeling_for_loop_bound
(loop_vec_info, tree *, struct loops *);
/* Utilities for creation and deletion of vec_info structs. */
@@ -605,16 +604,19 @@ slpeel_update_phi_nodes_for_guard (edge guard_true_edge, struct loop * loop)
/* Make the LOOP iterate NITERS times. This is done by adding a new IV
- that starts at zero, increases by one and its limit is NITERS. */
+ that starts at zero, increases by one and its limit is NITERS.
+
+ Assumption: the exit-condition of LOOP is the last stmt in the loop. */
static void
-slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters,
- tree begin_label, tree exit_label)
+slpeel_make_loop_iterate_ntimes (struct loop *loop, tree niters)
{
tree indx_before_incr, indx_after_incr, cond_stmt, cond;
tree orig_cond;
edge exit_edge = loop->exit_edges[0];
block_stmt_iterator loop_exit_bsi = bsi_last (exit_edge->src);
+ tree begin_label = tree_block_label (loop->latch);
+ tree exit_label = tree_block_label (loop->single_exit->dest);
/* Flow loop scan does not update loop->single_exit field. */
loop->single_exit = loop->exit_edges[0];
@@ -948,17 +950,13 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
and second loop preheader edge. */
flow_loop_scan (first_loop, LOOP_ALL);
flow_loop_scan (second_loop, LOOP_ALL);
+ /* Flow loop scan does not update loop->single_exit field. */
+ first_loop->single_exit = first_loop->exit_edges[0];
+ second_loop->single_exit = second_loop->exit_edges[0];
/* 3. Make first loop iterate FIRST_NITERS times, if needed. */
if (!update_first_loop_count)
- {
- tree first_loop_latch_lbl = tree_block_label (first_loop->latch);
- tree first_loop_exit_lbl = tree_block_label (first_exit_bb);
-
- slpeel_make_loop_iterate_ntimes (first_loop, first_niters,
- first_loop_latch_lbl,
- first_loop_exit_lbl);
- }
+ slpeel_make_loop_iterate_ntimes (first_loop, first_niters);
/* 4. Add the guard before first loop:
@@ -2791,16 +2789,11 @@ static void
vect_transform_loop_bound (loop_vec_info loop_vinfo, tree niters)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- edge exit_edge = loop->single_exit;
- block_stmt_iterator loop_exit_bsi = bsi_last (exit_edge->src);
- tree indx_before_incr, indx_after_incr;
tree orig_cond_expr;
HOST_WIDE_INT old_N = 0;
int vf;
- tree cond_stmt;
tree new_loop_bound;
bool symbol_niters;
- tree cond;
tree lb_type;
symbol_niters = !LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo);
@@ -2814,45 +2807,16 @@ vect_transform_loop_bound (loop_vec_info loop_vinfo, tree niters)
#ifdef ENABLE_CHECKING
gcc_assert (orig_cond_expr);
#endif
- gcc_assert (orig_cond_expr == bsi_stmt (loop_exit_bsi));
-
- create_iv (integer_zero_node, integer_one_node, NULL_TREE, loop,
- &loop_exit_bsi, false, &indx_before_incr, &indx_after_incr);
-
- /* bsi_insert is using BSI_NEW_STMT. We need to bump it back
- to point to the exit condition. */
- bsi_next (&loop_exit_bsi);
- gcc_assert (bsi_stmt (loop_exit_bsi) == orig_cond_expr);
/* new loop exit test: */
lb_type = TREE_TYPE (TREE_OPERAND (COND_EXPR_COND (orig_cond_expr), 1));
if (!symbol_niters)
- new_loop_bound = fold_convert (lb_type,
- build_int_cst (unsigned_type_node,
- old_N/vf));
+ new_loop_bound =
+ fold_convert (lb_type, build_int_cst (unsigned_type_node, old_N/vf));
else
new_loop_bound = niters;
- if (exit_edge->flags & EDGE_TRUE_VALUE) /* 'then' edge exits the loop. */
- cond = build2 (GE_EXPR, boolean_type_node,
- indx_after_incr, new_loop_bound);
- else /* 'then' edge loops back. */
- cond = build2 (LT_EXPR, boolean_type_node,
- indx_after_incr, new_loop_bound);
-
- cond_stmt = build3 (COND_EXPR, TREE_TYPE (orig_cond_expr), cond,
- COND_EXPR_THEN (orig_cond_expr),
- COND_EXPR_ELSE (orig_cond_expr));
-
- bsi_insert_before (&loop_exit_bsi, cond_stmt, BSI_SAME_STMT);
-
- /* remove old loop exit test: */
- bsi_remove (&loop_exit_bsi);
-
- if (vect_debug_details (NULL))
- print_generic_expr (dump_file, cond_stmt, TDF_SLIM);
-
- loop->nb_iterations = new_loop_bound;
+ slpeel_make_loop_iterate_ntimes (loop, new_loop_bound);
}
@@ -2978,8 +2942,8 @@ vect_update_ivs_after_vectorizer (struct loop *loop, tree niters)
unknown loop bound. */
static void
-vect_transform_for_unknown_loop_bound (loop_vec_info loop_vinfo, tree * ratio,
- struct loops *loops)
+vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree * ratio,
+ struct loops *loops)
{
tree ni_name, ratio_mult_vf_name;
@@ -3095,21 +3059,6 @@ vect_gen_niters_for_prolog_loop (loop_vec_info loop_vinfo, tree niters)
}
-/* Function vect_update_niters_after_peeling
-
- NITERS iterations were peeled from the loop represented by LOOP_VINFO.
- The new number of iterations is therefore original_niters - NITERS.
- Record the new number of iterations in LOOP_VINFO. */
-
-static void
-vect_update_niters_after_peeling (loop_vec_info loop_vinfo, tree niters)
-{
- tree n_iters = LOOP_VINFO_NITERS (loop_vinfo);
- LOOP_VINFO_NITERS (loop_vinfo) =
- build (MINUS_EXPR, integer_type_node, n_iters, niters);
-}
-
-
/* Function vect_update_inits_of_dr
NITERS iterations were peeled from LOOP. DR represents a data reference
@@ -3183,6 +3132,7 @@ vect_do_peeling_for_alignment (loop_vec_info loop_vinfo, struct loops *loops)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
tree niters_of_prolog_loop, ni_name;
+ tree n_iters;
if (vect_debug_details (NULL))
fprintf (dump_file, "\n<<vect_do_peeling_for_alignment>>\n");
@@ -3196,7 +3146,9 @@ vect_do_peeling_for_alignment (loop_vec_info loop_vinfo, struct loops *loops)
niters_of_prolog_loop, ni_name, false);
/* Update number of times loop executes. */
- vect_update_niters_after_peeling (loop_vinfo, niters_of_prolog_loop);
+ n_iters = LOOP_VINFO_NITERS (loop_vinfo);
+ LOOP_VINFO_NITERS (loop_vinfo) =
+ build (MINUS_EXPR, integer_type_node, n_iters, niters_of_prolog_loop);
/* Update all inits of access functions of all data refs. */
vect_update_inits_of_drs (loop_vinfo, niters_of_prolog_loop);
@@ -3233,32 +3185,21 @@ vect_transform_loop (loop_vec_info loop_vinfo,
/* Peel the loop if there are data refs with unknown alignment.
Only one data ref with unknown store is allowed. */
-
if (LOOP_DO_PEELING_FOR_ALIGNMENT (loop_vinfo))
vect_do_peeling_for_alignment (loop_vinfo, loops);
- /* If the loop has a symbolic number of iterations 'n'
- (i.e. it's not a compile time constant),
- then an epilog loop needs to be created. We therefore duplicate
- the initial loop. The original loop will be vectorized, and will compute
- the first (n/VF) iterations. The second copy of the loop will remain
- serial and will compute the remaining (n%VF) iterations.
+ /* If the loop has a symbolic number of iterations 'n' (i.e. it's not a
+ compile time constant), or it is a constant that doesn't divide by the
+ vectorization factor, then an epilog loop needs to be created.
+ We therefore duplicate the loop: the original loop will be vectorized,
+ and will compute the first (n/VF) iterations. The second copy of the loop
+ will remain scalar and will compute the remaining (n%VF) iterations.
(VF is the vectorization factor). */
- if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
- vect_transform_for_unknown_loop_bound (loop_vinfo, &ratio, loops);
-
- /* FORNOW: we'll treat the case where niters is constant and
-
- niters % vf != 0
-
- in the way similar to one with symbolic niters.
- For this we'll generate variable which value is equal to niters. */
-
- if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- && (LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0))
- vect_transform_for_unknown_loop_bound (loop_vinfo, &ratio, loops);
-
+ if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
+ || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
+ && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0))
+ vect_do_peeling_for_loop_bound (loop_vinfo, &ratio, loops);
/* 1) Make sure the loop header has exactly two entries
2) Make sure we have a preheader basic block. */