Commit d6901754 by Dorit Naishlos Committed by Dorit Nuzman

tree-vectorizer.c (slpeel_can_duplicate_loop_p): New name for function…

tree-vectorizer.c (slpeel_can_duplicate_loop_p): New name for function previously called verify_loop_for_duplication.

        * tree-vectorizer.c (slpeel_can_duplicate_loop_p): New name for function
        previously called verify_loop_for_duplication. All conditions compacted
        into one compound condition. Removed debug dumps.
        (vect_analyze_loop_with_symbolic_num_of_iters): Removed. Some of the
        functionality moved to vect_can_advance_ivs_p, and some to
        vect_analyze_loop_form.
        (vect_can_advance_ivs_p): New function. Contains functionality that was
        taken out of vect_analyze_loop_with_symbolic_num_of_iters.
        (slpeel_tree_peel_loop_to_edge): Call slpeel_can_duplicate_loop_p.
        (vect_analyze_operations): Call vect_can_advance_ivs_p and
        slpeel_can_duplicate_loop_p.
        (vect_get_loop_niters): Added documentation.
        (vect_analyze_loop_form): Check the loop entry always - not only in case
        of unknown loop bound. Create preheader and exit bb if necessary. Apply
        a check that used to take place in
        vect_analyze_loop_with_symbolic_num_of_iters.
        (vectorize_loops): Call verify_loop_closed_ssa under ENABLE_CHECKING.
        Remove redundant call to rewrite_into_loop_closed_ssa.
        (vect_compute_data_refs_alignment): Removed obsolete comment.

From-SVN: r90930
parent f88a8cfa
2004-11-19 Dorit Naishlos <dorit@il.ibm.com> 2004-11-19 Dorit Naishlos <dorit@il.ibm.com>
* tree-vectorizer.c (slpeel_can_duplicate_loop_p): New name for function
previously called verify_loop_for_duplication. All conditions compacted
into one compound condition. Removed debug dumps.
(vect_analyze_loop_with_symbolic_num_of_iters): Removed. Some of the
functionality moved to vect_can_advance_ivs_p, and some to
vect_analyze_loop_form.
(vect_can_advance_ivs_p): New function. Contains functionality that was
taken out of vect_analyze_loop_with_symbolic_num_of_iters.
(slpeel_tree_peel_loop_to_edge): Call slpeel_can_duplicate_loop_p.
(vect_analyze_operations): Call vect_can_advance_ivs_p and
slpeel_can_duplicate_loop_p.
(vect_get_loop_niters): Added documentation.
(vect_analyze_loop_form): Check the loop entry always - not only in case
of unknown loop bound. Create preheader and exit bb if necessary. Apply
a check that used to take place in
vect_analyze_loop_with_symbolic_num_of_iters.
(vectorize_loops): Call verify_loop_closed_ssa under ENABLE_CHECKING.
Remove redundant call to rewrite_into_loop_closed_ssa.
(vect_compute_data_refs_alignment): Removed obsolete comment.
2004-11-19 Dorit Naishlos <dorit@il.ibm.com>
* tree-vectorizer.c (slpeel_tree_peel_loop_to_edge): New name for * tree-vectorizer.c (slpeel_tree_peel_loop_to_edge): New name for
function previously called tree_duplicate_loop_to_edge. function previously called tree_duplicate_loop_to_edge.
(slpeel_tree_duplicate_loop_to_edge_cfg): New name for function (slpeel_tree_duplicate_loop_to_edge_cfg): New name for function
......
...@@ -167,6 +167,7 @@ static void slpeel_update_phis_for_duplicate_loop ...@@ -167,6 +167,7 @@ static void slpeel_update_phis_for_duplicate_loop
static void slpeel_update_phi_nodes_for_guard (edge, struct loop *); 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, tree, tree);
static edge slpeel_add_loop_guard (basic_block, tree, basic_block); 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); static void allocate_new_names (bitmap);
static void rename_use_op (use_operand_p); static void rename_use_op (use_operand_p);
static void rename_def_op (def_operand_p, tree); static void rename_def_op (def_operand_p, tree);
...@@ -217,8 +218,7 @@ static bool vect_get_first_index (tree, tree *); ...@@ -217,8 +218,7 @@ static bool vect_get_first_index (tree, tree *);
static bool vect_can_force_dr_alignment_p (tree, unsigned int); static bool vect_can_force_dr_alignment_p (tree, unsigned int);
static struct data_reference * vect_analyze_pointer_ref_access static struct data_reference * vect_analyze_pointer_ref_access
(tree, tree, bool); (tree, tree, bool);
static bool vect_analyze_loop_with_symbolic_num_of_iters static bool vect_can_advance_ivs_p (struct loop *);
(tree niters, struct loop *loop);
static tree vect_get_base_and_bit_offset static tree vect_get_base_and_bit_offset
(struct data_reference *, tree, tree, loop_vec_info, tree *, bool*); (struct data_reference *, tree, tree, loop_vec_info, tree *, bool*);
static struct data_reference * vect_analyze_pointer_ref_access static struct data_reference * vect_analyze_pointer_ref_access
...@@ -799,83 +799,37 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb) ...@@ -799,83 +799,37 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond, basic_block exit_bb)
} }
/* This function verifies that certain restrictions apply to LOOP. */ /* This function verifies that the following restrictions apply to LOOP:
(1) it is innermost
(2) it consists of exactly 2 basic blocks - header, and an empty latch.
(3) it is single entry, single exit
(4) its exit condition is the last stmt in the header
(5) E is the entry/exit edge of LOOP.
*/
static bool static bool
slpeel_verify_loop_for_duplication (struct loop *loop, slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
bool update_first_loop_count, edge e)
{ {
edge exit_e = loop->exit_edges [0]; edge exit_e = loop->exit_edges [0];
edge entry_e = loop_preheader_edge (loop); edge entry_e = loop_preheader_edge (loop);
/* We duplicate only innermost loops. */
if (loop->inner)
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file,
"Loop duplication failed. Loop is not innermost.\n");
return false;
}
/* Only loops with 1 exit. */
if (loop->num_exits != 1)
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file,
"More than one exit from loop.\n");
return false;
}
/* Only loops with 1 entry. */
if (loop->num_entries != 1)
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file,
"More than one exit from loop.\n");
return false;
}
/* All loops has outers, the only case loop->outer is NULL is for
the function itself. */
if (!loop->outer)
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file,
"Loop is outer-most loop.\n");
return false;
}
/* Verify that new IV can be created and loop condition
can be changed to make first loop iterate first_niters times. */
if (!update_first_loop_count)
{
tree orig_cond = get_loop_exit_condition (loop); tree orig_cond = get_loop_exit_condition (loop);
block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src); block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
if (!orig_cond) if (any_marked_for_rewrite_p ())
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file,
"Loop has no exit condition.\n");
return false; return false;
}
if (orig_cond != bsi_stmt (loop_exit_bsi))
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file,
"Loop exit condition is not loop header last stmt.\n");
return false;
}
}
/* Make sure E is either an entry or an exit edge. */ if (loop->inner
if (e != exit_e && e != entry_e) /* All loops have an outer scope; the only case loop->outer is NULL is for
{ the function itself. */
if (vect_debug_stats (loop) || vect_debug_details (loop)) || !loop->outer
fprintf (dump_file, || loop->num_nodes != 2
"E is not loop entry or exit edge.\n"); || !empty_block_p (loop->latch)
|| loop->num_exits != 1
|| loop->num_entries != 1
/* Verify that new loop exit condition can be trivially modified. */
|| (!orig_cond || orig_cond != bsi_stmt (loop_exit_bsi))
|| (e != exit_e && e != entry_e))
return false; return false;
}
return true; return true;
} }
...@@ -949,9 +903,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops, ...@@ -949,9 +903,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, struct loops *loops,
basic_block pre_header_bb; basic_block pre_header_bb;
edge exit_e = loop->exit_edges [0]; edge exit_e = loop->exit_edges [0];
gcc_assert (!any_marked_for_rewrite_p ()); if (!slpeel_can_duplicate_loop_p (loop, e))
if (!slpeel_verify_loop_for_duplication (loop, update_first_loop_count, e))
return NULL; return NULL;
/* We have to initialize cfg_hooks. Then, when calling /* We have to initialize cfg_hooks. Then, when calling
...@@ -3595,23 +3547,26 @@ vect_analyze_operations (loop_vec_info loop_vinfo) ...@@ -3595,23 +3547,26 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
} }
LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor; LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) && vect_debug_details (NULL))
if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
&& vect_debug_details (NULL))
fprintf (dump_file, fprintf (dump_file,
"vectorization_factor = %d, niters = " HOST_WIDE_INT_PRINT_DEC, "vectorization_factor = %d, niters = " HOST_WIDE_INT_PRINT_DEC,
vectorization_factor, LOOP_VINFO_INT_NITERS (loop_vinfo)); vectorization_factor, LOOP_VINFO_INT_NITERS (loop_vinfo));
if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
&& LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0) || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0)
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file, "epilog loop required.");
if (!vect_can_advance_ivs_p (loop))
{ {
/* In this case we have to generate epilog loop, that if (vect_debug_stats (loop) || vect_debug_details (loop))
can be done only for loops with one entry edge. */ fprintf (dump_file, "not vectorized: can't create epilog loop 1.");
if (LOOP_VINFO_LOOP (loop_vinfo)->num_entries != 1 return false;
|| !(LOOP_VINFO_LOOP (loop_vinfo)->pre_header)) }
if (!slpeel_can_duplicate_loop_p (loop, loop->exit_edges[0]))
{ {
if (vect_debug_stats (loop) || vect_debug_details (loop)) if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file, "not vectorized: more than one entry."); fprintf (dump_file, "not vectorized: can't create epilog loop 2.");
return false; return false;
} }
} }
...@@ -4358,9 +4313,7 @@ vect_compute_data_refs_alignment (loop_vec_info loop_vinfo) ...@@ -4358,9 +4313,7 @@ vect_compute_data_refs_alignment (loop_vec_info loop_vinfo)
FOR NOW: we assume that whatever versioning/peeling takes place, only the FOR NOW: we assume that whatever versioning/peeling takes place, only the
original loop is to be vectorized; Any other loops that are created by original loop is to be vectorized; Any other loops that are created by
the transformations performed in this pass - are not supposed to be the transformations performed in this pass - are not supposed to be
vectorized. This restriction will be relaxed. vectorized. This restriction will be relaxed. */
FOR NOW: No transformation is actually performed. TODO. */
static void static void
vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
...@@ -5347,7 +5300,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) ...@@ -5347,7 +5300,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
} }
/* Function vect_analyze_loop_with_symbolic_num_of_iters. /* Function vect_can_advance_ivs_p
In case the number of iterations that LOOP iterates in unknown at compile In case the number of iterations that LOOP iterates in unknown at compile
time, an epilog loop will be generated, and the loop induction variables time, an epilog loop will be generated, and the loop induction variables
...@@ -5357,36 +5310,11 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) ...@@ -5357,36 +5310,11 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
These restrictions will be relaxed in the future. */ These restrictions will be relaxed in the future. */
static bool static bool
vect_analyze_loop_with_symbolic_num_of_iters (tree niters, vect_can_advance_ivs_p (struct loop *loop)
struct loop *loop)
{ {
basic_block bb = loop->header; basic_block bb = loop->header;
tree phi; tree phi;
if (vect_debug_details (NULL))
fprintf (dump_file,
"\n<<vect_analyze_loop_with_symbolic_num_of_iters>>\n");
if (chrec_contains_undetermined (niters))
{
if (vect_debug_details (NULL))
fprintf (dump_file, "Infinite number of iterations.");
return false;
}
if (!niters)
{
if (vect_debug_details (NULL))
fprintf (dump_file, "niters is NULL pointer.");
return false;
}
if (vect_debug_details (NULL))
{
fprintf (dump_file, "Symbolic number of iterations is ");
print_generic_expr (dump_file, niters, TDF_DETAILS);
}
/* Analyze phi functions of the loop header. */ /* Analyze phi functions of the loop header. */
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
...@@ -5446,7 +5374,10 @@ vect_analyze_loop_with_symbolic_num_of_iters (tree niters, ...@@ -5446,7 +5374,10 @@ vect_analyze_loop_with_symbolic_num_of_iters (tree niters,
/* Function vect_get_loop_niters. /* Function vect_get_loop_niters.
Determine how many iterations the loop is executed. */ Determine how many iterations the loop is executed.
If an expression that represents the number of iterations
can be constructed, place it in NUMBER_OF_ITERATIONS.
Return the loop exit condition. */
static tree static tree
vect_get_loop_niters (struct loop *loop, tree *number_of_iterations) vect_get_loop_niters (struct loop *loop, tree *number_of_iterations)
...@@ -5490,13 +5421,16 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -5490,13 +5421,16 @@ vect_analyze_loop_form (struct loop *loop)
loop_vec_info loop_vinfo; loop_vec_info loop_vinfo;
tree loop_cond; tree loop_cond;
tree number_of_iterations = NULL; tree number_of_iterations = NULL;
bool rescan = false;
if (vect_debug_details (loop)) if (vect_debug_details (loop))
fprintf (dump_file, "\n<<vect_analyze_loop_form>>\n"); fprintf (dump_file, "\n<<vect_analyze_loop_form>>\n");
if (loop->inner if (loop->inner
|| !loop->single_exit || !loop->single_exit
|| loop->num_nodes != 2) || loop->num_nodes != 2
|| EDGE_COUNT (loop->header->preds) != 2
|| loop->num_entries != 1)
{ {
if (vect_debug_stats (loop) || vect_debug_details (loop)) if (vect_debug_stats (loop) || vect_debug_details (loop))
{ {
...@@ -5507,6 +5441,10 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -5507,6 +5441,10 @@ vect_analyze_loop_form (struct loop *loop)
fprintf (dump_file, "multiple exits."); fprintf (dump_file, "multiple exits.");
else if (loop->num_nodes != 2) else if (loop->num_nodes != 2)
fprintf (dump_file, "too many BBs in loop."); fprintf (dump_file, "too many BBs in loop.");
else if (EDGE_COUNT (loop->header->preds) != 2)
fprintf (dump_file, "too many incoming edges.");
else if (loop->num_entries != 1)
fprintf (dump_file, "too many entries.");
} }
return NULL; return NULL;
...@@ -5523,6 +5461,27 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -5523,6 +5461,27 @@ vect_analyze_loop_form (struct loop *loop)
return NULL; return NULL;
} }
/* Make sure we have a preheader basic block. */
if (!loop->pre_header)
{
rescan = true;
loop_split_edge_with (loop_preheader_edge (loop), NULL);
}
/* Make sure there exists a single-predecessor exit bb: */
if (EDGE_COUNT (loop->exit_edges[0]->dest->preds) != 1)
{
rescan = true;
loop_split_edge_with (loop->exit_edges[0], NULL);
}
if (rescan)
{
flow_loop_scan (loop, LOOP_ALL);
/* Flow loop scan does not update loop->single_exit field. */
loop->single_exit = loop->exit_edges[0];
}
if (empty_block_p (loop->header)) if (empty_block_p (loop->header))
{ {
if (vect_debug_stats (loop) || vect_debug_details (loop)) if (vect_debug_stats (loop) || vect_debug_details (loop))
...@@ -5546,32 +5505,23 @@ vect_analyze_loop_form (struct loop *loop) ...@@ -5546,32 +5505,23 @@ vect_analyze_loop_form (struct loop *loop)
return NULL; return NULL;
} }
if (chrec_contains_undetermined (number_of_iterations))
{
if (vect_debug_details (NULL))
fprintf (dump_file, "Infinite number of iterations.");
return false;
}
loop_vinfo = new_loop_vec_info (loop); loop_vinfo = new_loop_vec_info (loop);
LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations; LOOP_VINFO_NITERS (loop_vinfo) = number_of_iterations;
if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file, "loop bound unknown.");
/* Unknown loop bound. */ if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo))
if (!vect_analyze_loop_with_symbolic_num_of_iters
(number_of_iterations, loop))
{
if (vect_debug_stats (loop) || vect_debug_details (loop))
fprintf (dump_file,
"not vectorized: can't determine loop bound.");
return NULL;
}
else
{ {
/* We need only one loop entry for unknown loop bound support. */ if (vect_debug_details (loop))
if (loop->num_entries != 1 || !loop->pre_header)
{ {
if (vect_debug_stats (loop) || vect_debug_details (loop)) fprintf (dump_file, "loop bound unknown.\n");
fprintf (dump_file, fprintf (dump_file, "Symbolic number of iterations is ");
"not vectorized: more than one loop entry."); print_generic_expr (dump_file, number_of_iterations, TDF_DETAILS);
return NULL;
}
} }
} }
else else
...@@ -5739,6 +5689,10 @@ vectorize_loops (struct loops *loops) ...@@ -5739,6 +5689,10 @@ vectorize_loops (struct loops *loops)
return; return;
} }
#ifdef ENABLE_CHECKING
verify_loop_closed_ssa ();
#endif
compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for); compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for);
/* ----------- Analyze loops. ----------- */ /* ----------- Analyze loops. ----------- */
...@@ -5785,13 +5739,6 @@ vectorize_loops (struct loops *loops) ...@@ -5785,13 +5739,6 @@ vectorize_loops (struct loops *loops)
} }
rewrite_into_ssa (false); rewrite_into_ssa (false);
if (!bitmap_empty_p (vars_to_rename)) rewrite_into_loop_closed_ssa (); /* FORNOW */
{
/* The rewrite of ssa names may cause violation of loop closed ssa
form invariants. TODO -- avoid these rewrites completely.
Information in virtual phi nodes is sufficient for it. */
rewrite_into_loop_closed_ssa ();
}
rewrite_into_loop_closed_ssa ();
bitmap_clear (vars_to_rename); bitmap_clear (vars_to_rename);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment