+2006-11-22 Zdenek Dvorak <dvorakz@suse.cz>
+
+ * tree-loop-linear.c (linear_transform_loops): Use single_exit accessor
+ functions.
+ * tree-ssa-loop-niter.c (loop_only_exit_p): Ditto.
+ * cfgloopmanip.c (update_single_exits_after_duplication,
+ update_single_exit_for_duplicated_loop, loop_version): Ditto.
+ * tree-scalar-evolution.c (get_loop_exit_condition,
+ get_exit_conditions_rec, loop_closed_phi_def,
+ number_of_iterations_in_loop, scev_const_prop): Ditto.
+ * tree-ssa-loop-ivopts.c (single_dom_exit): Ditto.
+ * modulo-sched.c (generate_prolog_epilog, loop_canon_p, sms_schedule):
+ Ditto.
+ * tree-ssa-loop-ivcanon.c (canonicalize_loop_induction_variables):
+ Ditto.
+ * tree-vectorizer.c (slpeel_update_phis_for_duplicate_loop,
+ slpeel_update_phi_nodes_for_guard1, slpeel_update_phi_nodes_for_guard2,
+ slpeel_make_loop_iterate_ntimes,
+ slpeel_tree_duplicate_loop_to_edge_cfg, slpeel_can_duplicate_loop_p,
+ slpeel_verify_cfg_after_peeling, slpeel_tree_peel_loop_to_edge):
+ Ditto.
+ * tree-if-conv.c (if_convertible_loop_p): Ditto.
+ * tree-vect-analyze.c (vect_analyze_operations, vect_stmt_relevant_p,
+ vect_analyze_loop_form): Ditto.
+ * lambda-code.c (lambda_loopnest_to_gcc_loopnest, exit_phi_for_loop_p,
+ can_convert_to_perfect_nest, perfect_nestify): Ditto.
+ * tree-vect-transform.c (vect_create_epilog_for_reduction,
+ vect_update_ivs_after_vectorizer, vect_do_peeling_for_loop_bound,
+ vect_transform_loop): Ditto.
+ * cfgloop.c (mark_single_exit_loops, verify_loop_structure): Ditto.
+ (single_exit, set_single_exit): New functions.
+ * cfgloop.h (struct loop): Rename single_exit field to single_exit_.
+ (single_exit, set_single_exit): Declare.
+ * doc/loop.texi: Undocument single_exit field. Document single_exit
+ accessor function.
+
2006-11-22 Zdenek Dvorak <dvorakz@suse.cz>
PR tree-optimization/29902
{
loop = loops->parray[i];
if (loop)
- loop->single_exit = NULL;
+ set_single_exit (loop, NULL);
}
FOR_EACH_BB (bb)
{
/* If we have already seen an exit, mark this by the edge that
surely does not occur as any exit. */
- if (loop->single_exit)
- loop->single_exit = single_succ_edge (ENTRY_BLOCK_PTR);
+ if (single_exit (loop))
+ set_single_exit (loop, single_succ_edge (ENTRY_BLOCK_PTR));
else
- loop->single_exit = e;
+ set_single_exit (loop, e);
}
}
}
if (!loop)
continue;
- if (loop->single_exit == single_succ_edge (ENTRY_BLOCK_PTR))
- loop->single_exit = NULL;
+ if (single_exit (loop) == single_succ_edge (ENTRY_BLOCK_PTR))
+ set_single_exit (loop, NULL);
}
loops->state |= LOOPS_HAVE_MARKED_SINGLE_EXITS;
loop = loop->outer)
{
sizes[loop->num]++;
- if (loop->single_exit
- && loop->single_exit != e)
+ if (single_exit (loop)
+ && single_exit (loop) != e)
{
error ("wrong single exit %d->%d recorded for loop %d",
- loop->single_exit->src->index,
- loop->single_exit->dest->index,
+ single_exit (loop)->src->index,
+ single_exit (loop)->dest->index,
loop->num);
error ("right exit is %d->%d",
e->src->index, e->dest->index);
continue;
if (sizes[i] == 1
- && !loop->single_exit)
+ && !single_exit (loop))
{
error ("single exit not recorded for loop %d", loop->num);
err = 1;
}
if (sizes[i] != 1
- && loop->single_exit)
+ && single_exit (loop))
{
error ("loop %d should not have single exit (%d -> %d)",
loop->num,
- loop->single_exit->src->index,
- loop->single_exit->dest->index);
+ single_exit (loop)->src->index,
+ single_exit (loop)->dest->index);
err = 1;
}
}
return (flow_bb_inside_loop_p (loop, e->src)
&& !flow_bb_inside_loop_p (loop, e->dest));
}
+
+/* Returns the single exit edge of LOOP, or NULL if LOOP has either no exit
+ or more than one exit. */
+
+edge
+single_exit (const struct loop *loop)
+{
+ return loop->single_exit_;
+}
+
+/* Records E as a single exit edge of LOOP. */
+
+void
+set_single_exit (struct loop *loop, edge e)
+{
+ loop->single_exit_ = e;
+}
struct nb_iter_bound *bounds;
/* If not NULL, loop has just single exit edge stored here (edges to the
- EXIT_BLOCK_PTR do not count. */
- edge single_exit;
+ EXIT_BLOCK_PTR do not count. Do not use direcly, this field should
+ only be accessed via single_exit/set_single_exit functions. */
+ edge single_exit_;
/* True when the loop does not carry data dependences, and
consequently the iterations can be executed in any order. False
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
extern basic_block *get_loop_body_in_bfs_order (const struct loop *);
extern VEC (edge, heap) *get_loop_exit_edges (const struct loop *);
+edge single_exit (const struct loop *);
+void set_single_exit (struct loop *, edge);
extern unsigned num_loop_branches (const struct loop *);
extern edge loop_preheader_edge (const struct loop *);
for (; loop->outer; loop = loop->outer)
{
- if (!loop->single_exit)
+ if (!single_exit (loop))
continue;
- if (loop->single_exit->src->flags & BB_DUPLICATED)
- loop->single_exit = NULL;
+ if (single_exit (loop)->src->flags & BB_DUPLICATED)
+ set_single_exit (loop, NULL);
}
for (i = 0; i < nbbs; i++)
{
struct loop *copy = loop->copy;
basic_block src, dest;
- edge exit = loop->single_exit;
+ edge exit = single_exit (loop);
if (!exit)
return;
exit = find_edge (src, dest);
gcc_assert (exit != NULL);
- copy->single_exit = exit;
+ set_single_exit (copy, exit);
}
/* Updates single exit information for copies of ORIG_LOOPS and their subloops.
cond_bb, true_edge, false_edge,
false /* Do not redirect all edges. */);
- exit = loop->single_exit;
+ exit = single_exit (loop);
if (exit)
- nloop->single_exit = find_edge (get_bb_copy (exit->src), exit->dest);
+ set_single_exit (nloop, find_edge (get_bb_copy (exit->src), exit->dest));
/* loopify redirected latch_edge. Update its PENDING_STMTS. */
lv_flush_pending_stmts (latch_edge);
are in such an irreducible region (but it is set for the entry and exit
edges of such a loop, if they lead to/from this region).
@item @code{LOOPS_HAVE_MARKED_SINGLE_EXITS}: If a loop has exactly one
-exit edge, this edge is stored in @code{single_exit} field of the loop
-structure. @code{NULL} is stored there otherwise.
+exit edge, this edge is recorded in the loop structure. @code{single_exit}
+function can be used to retrieve this edge.
@end itemize
These properties may also be computed/enforced later, using functions
number of super-loops of the loop.
@item @code{outer}, @code{inner}, @code{next}: The super-loop, the first
sub-loop, and the sibling of the loop in the loops tree.
-@item @code{single_exit}: The exit edge of the loop, if the loop has
-exactly one exit and the loops were analyzed with
-LOOPS_HAVE_MARKED_SINGLE_EXITS.
@end itemize
There are other fields in the loop structures, many of them used only by
@code{get_loop_body_in_bfs_order}: Enumerates the basic blocks in the
loop in depth-first search order in reversed CFG, ordered by dominance
relation, and breath-first search order, respectively.
+@item @code{single_exit}: Returns the single exit edge of the loop, or
+@code{NULL} if the loop has more than one exit. You can only use this
+function if LOOPS_HAVE_MARKED_SINGLE_EXITS property is used.
@item @code{get_loop_exit_edges}: Enumerates the exit edges of a loop.
@item @code{just_once_each_iteration_p}: Returns true if the basic block
is executed exactly once during each iteration of a loop (that is, it
type,
new_ivs,
invariants, MIN_EXPR, &stmts);
- exit = temp->single_exit;
+ exit = single_exit (temp);
exitcond = get_loop_exit_condition (temp);
bb = bb_for_stmt (exitcond);
bsi = bsi_start (bb);
if (TREE_CODE (stmt) != PHI_NODE
|| PHI_NUM_ARGS (stmt) != 1
- || bb_for_stmt (stmt) != loop->single_exit->dest)
+ || bb_for_stmt (stmt) != single_exit (loop)->dest)
return false;
return true;
/* We also need to make sure the loop exit only has simple copy phis in it,
otherwise we don't know how to transform it into a perfect nest right
now. */
- exitdest = loop->single_exit->dest;
+ exitdest = single_exit (loop)->dest;
for (phi = phi_nodes (exitdest); phi; phi = PHI_CHAIN (phi))
if (PHI_NUM_ARGS (phi) != 1)
htab_t replacements = NULL;
/* Create the new loop. */
- olddest = loop->single_exit->dest;
- preheaderbb = split_edge (loop->single_exit);
+ olddest = single_exit (loop)->dest;
+ preheaderbb = split_edge (single_exit (loop));
headerbb = create_empty_bb (EXIT_BLOCK_PTR->prev_bb);
/* Push the exit phi nodes that we are moving. */
newloop = duplicate_loop (loops, loop, olddest->loop_father);
newloop->header = headerbb;
newloop->latch = latchbb;
- newloop->single_exit = e;
+ set_single_exit (newloop, e);
add_bb_to_loop (latchbb, newloop);
add_bb_to_loop (bodybb, newloop);
add_bb_to_loop (headerbb, newloop);
set_immediate_dominator (CDI_DOMINATORS, bodybb, headerbb);
set_immediate_dominator (CDI_DOMINATORS, headerbb, preheaderbb);
set_immediate_dominator (CDI_DOMINATORS, preheaderbb,
- loop->single_exit->src);
+ single_exit (loop)->src);
set_immediate_dominator (CDI_DOMINATORS, latchbb, bodybb);
set_immediate_dominator (CDI_DOMINATORS, olddest, bodybb);
/* Create the new iv. */
duplicate_insns_of_cycles (ps, i + 1, last_stage, 0);
/* Put the epilogue on the exit edge. */
- gcc_assert (loop->single_exit);
- e = loop->single_exit;
+ gcc_assert (single_exit (loop));
+ e = single_exit (loop);
split_edge_and_insert (e, get_insns());
end_sequence ();
}
if (loop->inner || ! loop->outer)
return false;
- if (!loop->single_exit)
+ if (!single_exit (loop))
{
if (dump_file)
{
get_ebb_head_tail (bb, bb, &head, &tail);
latch_edge = loop_latch_edge (loop);
- gcc_assert (loop->single_exit);
- if (loop->single_exit->count)
- trip_count = latch_edge->count / loop->single_exit->count;
+ gcc_assert (single_exit (loop));
+ if (single_exit (loop)->count)
+ trip_count = latch_edge->count / single_exit (loop)->count;
/* Perfrom SMS only on loops that their average count is above threshold. */
if ( latch_edge->count
- && (latch_edge->count < loop->single_exit->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
+ && (latch_edge->count < single_exit (loop)->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
{
if (dump_file)
{
get_ebb_head_tail (loop->header, loop->header, &head, &tail);
latch_edge = loop_latch_edge (loop);
- gcc_assert (loop->single_exit);
- if (loop->single_exit->count)
- trip_count = latch_edge->count / loop->single_exit->count;
+ gcc_assert (single_exit (loop));
+ if (single_exit (loop)->count)
+ trip_count = latch_edge->count / single_exit (loop)->count;
if (dump_file)
{
}
/* More than one loop exit is too much to handle. */
- if (!loop->single_exit)
+ if (!single_exit (loop))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "multiple exits\n");
...
}
} */
- if (!loop_nest || !loop_nest->inner || !loop_nest->single_exit)
+ if (!loop_nest || !loop_nest->inner || !single_exit (loop_nest))
continue;
VEC_truncate (tree, oldivs, 0);
VEC_truncate (tree, invariants, 0);
for (temp = loop_nest->inner; temp; temp = temp->inner)
{
/* If we have a sibling loop or multiple exit edges, jump ship. */
- if (temp->next || !temp->single_exit)
+ if (temp->next || !single_exit (temp))
{
problem = true;
break;
get_loop_exit_condition (struct loop *loop)
{
tree res = NULL_TREE;
- edge exit_edge = loop->single_exit;
-
+ edge exit_edge = single_exit (loop);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "(get_loop_exit_condition \n ");
get_exit_conditions_rec (loop->inner, exit_conditions);
get_exit_conditions_rec (loop->next, exit_conditions);
- if (loop->single_exit)
+ if (single_exit (loop))
{
tree loop_condition = get_loop_exit_condition (loop);
return NULL_TREE;
loop = loop_containing_stmt (SSA_NAME_DEF_STMT (var));
- exit = loop->single_exit;
+ exit = single_exit (loop);
if (!exit)
return NULL_TREE;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "(number_of_iterations_in_loop\n");
- exit = loop->single_exit;
+ exit = single_exit (loop);
if (!exit)
goto end;
/* If we do not know exact number of iterations of the loop, we cannot
replace the final value. */
- exit = loop->single_exit;
+ exit = single_exit (loop);
if (!exit)
continue;
niter = number_of_iterations_in_loop (loop);
if (TREE_CODE (niter) == INTEGER_CST)
{
- exit = loop->single_exit;
+ exit = single_exit (loop);
if (!just_once_each_iteration_p (loop, exit->src))
return false;
{
/* If the loop has more than one exit, try checking all of them
for # of iterations determinable through scev. */
- if (!loop->single_exit)
+ if (!single_exit (loop))
niter = find_loop_niter (loop, &exit);
/* Finally if everything else fails, try brute force evaluation. */
edge
single_dom_exit (struct loop *loop)
{
- edge exit = loop->single_exit;
+ edge exit = single_exit (loop);
if (!exit)
return NULL;
unsigned i;
tree call;
- if (exit != loop->single_exit)
+ if (exit != single_exit (loop))
return false;
body = get_loop_body (loop);
"not vectorized: can't create epilog loop 1.");
return false;
}
- if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit))
+ if (!slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS))
fprintf (vect_dump,
/* We expect all such uses to be in the loop exit phis
(because of loop closed form) */
gcc_assert (TREE_CODE (USE_STMT (use_p)) == PHI_NODE);
- gcc_assert (bb == loop->single_exit->dest);
+ gcc_assert (bb == single_exit (loop)->dest);
*live_p = true;
}
return NULL;
}
- if (!loop->single_exit
+ if (!single_exit (loop)
|| loop->num_nodes != 2
|| EDGE_COUNT (loop->header->preds) != 2)
{
if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
{
- if (!loop->single_exit)
+ if (!single_exit (loop))
fprintf (vect_dump, "not vectorized: multiple exits.");
else if (loop->num_nodes != 2)
fprintf (vect_dump, "not vectorized: too many BBs in loop.");
}
/* Make sure there exists a single-predecessor exit bb: */
- if (!single_pred_p (loop->single_exit->dest))
+ if (!single_pred_p (single_exit (loop)->dest))
{
- edge e = loop->single_exit;
+ edge e = single_exit (loop);
if (!(e->flags & EDGE_ABNORMAL))
{
split_loop_exit_edge (e);
/* 2.1 Create new loop-exit-phi to preserve loop-closed form:
v_out1 = phi <v_loop> */
- exit_bb = loop->single_exit->dest;
+ exit_bb = single_exit (loop)->dest;
new_phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
- SET_PHI_ARG_DEF (new_phi, loop->single_exit->dest_idx, vect_def);
+ SET_PHI_ARG_DEF (new_phi, single_exit (loop)->dest_idx, vect_def);
exit_bsi = bsi_start (exit_bb);
/* 2.2 Get the relevant tree-code to use in the epilog for schemes 2,3
edge update_e)
{
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- basic_block exit_bb = loop->single_exit->dest;
+ basic_block exit_bb = single_exit (loop)->dest;
tree phi, phi1;
basic_block update_bb = update_e->dest;
&ratio_mult_vf_name, ratio);
loop_num = loop->num;
- new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, loop->single_exit,
+ new_loop = slpeel_tree_peel_loop_to_edge (loop, loops, single_exit (loop),
ratio_mult_vf_name, ni_name, false);
gcc_assert (new_loop);
gcc_assert (loop_num == loop->num);
is on the path where the LOOP IVs are used and need to be updated. */
preheader = loop_preheader_edge (new_loop)->src;
- if (EDGE_PRED (preheader, 0)->src == loop->single_exit->dest)
+ if (EDGE_PRED (preheader, 0)->src == single_exit (loop)->dest)
update_e = EDGE_PRED (preheader, 0);
else
update_e = EDGE_PRED (preheader, 1);
here by adding a new (empty) block on the exit-edge of the loop,
with the proper loop-exit phis to maintain loop-closed-form. **/
- merge_bb = loop->single_exit->dest;
+ merge_bb = single_exit (loop)->dest;
gcc_assert (EDGE_COUNT (merge_bb->preds) == 2);
- new_exit_bb = split_edge (loop->single_exit);
- new_exit_e = loop->single_exit;
+ new_exit_bb = split_edge (single_exit (loop));
+ new_exit_e = single_exit (loop);
e = EDGE_SUCC (new_exit_bb, 0);
for (orig_phi = phi_nodes (merge_bb); orig_phi;
tree def;
edge orig_loop_latch = loop_latch_edge (orig_loop);
edge orig_entry_e = loop_preheader_edge (orig_loop);
- edge new_loop_exit_e = new_loop->single_exit;
+ edge new_loop_exit_e = single_exit (new_loop);
edge new_loop_entry_e = loop_preheader_edge (new_loop);
edge entry_arg_e = (after ? orig_loop_latch : orig_entry_e);
tree name;
/* Create new bb between loop and new_merge_bb. */
- *new_exit_bb = split_edge (loop->single_exit);
+ *new_exit_bb = split_edge (single_exit (loop));
new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
*new_exit_bb);
/* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop. */
- add_phi_arg (new_phi, loop_arg, loop->single_exit);
+ add_phi_arg (new_phi, loop_arg, single_exit (loop));
/* 2.3. Update phi in successor of NEW_EXIT_BB: */
gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
tree arg;
/* Create new bb between loop and new_merge_bb. */
- *new_exit_bb = split_edge (loop->single_exit);
+ *new_exit_bb = split_edge (single_exit (loop));
new_exit_e = EDGE_SUCC (*new_exit_bb, 0);
*new_exit_bb);
/* 2.2. NEW_EXIT_BB has one incoming edge: the exit-edge of the loop. */
- add_phi_arg (new_phi, loop_arg, loop->single_exit);
+ add_phi_arg (new_phi, loop_arg, single_exit (loop));
/* 2.3. Update phi in successor of NEW_EXIT_BB: */
gcc_assert (PHI_ARG_DEF_FROM_EDGE (update_phi2, new_exit_e) == loop_arg);
{
tree indx_before_incr, indx_after_incr, cond_stmt, cond;
tree orig_cond;
- edge exit_edge = loop->single_exit;
+ edge exit_edge = single_exit (loop);
block_stmt_iterator loop_cond_bsi;
block_stmt_iterator incr_bsi;
bool insert_after;
tree begin_label = tree_block_label (loop->latch);
- tree exit_label = tree_block_label (loop->single_exit->dest);
+ tree exit_label = tree_block_label (single_exit (loop)->dest);
tree init = build_int_cst (TREE_TYPE (niters), 0);
tree step = build_int_cst (TREE_TYPE (niters), 1);
tree then_label;
bool was_imm_dom;
basic_block exit_dest;
tree phi, phi_arg;
+ edge exit, new_exit;
- at_exit = (e == loop->single_exit);
+ at_exit = (e == single_exit (loop));
if (!at_exit && e != loop_preheader_edge (loop))
return NULL;
return NULL;
}
- exit_dest = loop->single_exit->dest;
+ exit_dest = single_exit (loop)->dest;
was_imm_dom = (get_immediate_dominator (CDI_DOMINATORS,
exit_dest) == loop->header ?
true : false);
new_bbs = XNEWVEC (basic_block, loop->num_nodes);
+ exit = single_exit (loop);
copy_bbs (bbs, loop->num_nodes, new_bbs,
- &loop->single_exit, 1, &new_loop->single_exit, NULL,
+ &exit, 1, &new_exit, NULL,
e->src);
+ set_single_exit (new_loop, new_exit);
/* Duplicating phi args at exit bbs as coming
also from exit of duplicated loop. */
for (phi = phi_nodes (exit_dest); phi; phi = PHI_CHAIN (phi))
{
- phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, loop->single_exit);
+ phi_arg = PHI_ARG_DEF_FROM_EDGE (phi, single_exit (loop));
if (phi_arg)
{
edge new_loop_exit_edge;
bool
slpeel_can_duplicate_loop_p (struct loop *loop, edge e)
{
- edge exit_e = loop->single_exit;
+ edge exit_e = single_exit (loop);
edge entry_e = loop_preheader_edge (loop);
tree orig_cond = get_loop_exit_condition (loop);
block_stmt_iterator loop_exit_bsi = bsi_last (exit_e->src);
|| !loop->outer
|| loop->num_nodes != 2
|| !empty_block_p (loop->latch)
- || !loop->single_exit
+ || !single_exit (loop)
/* 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))
slpeel_verify_cfg_after_peeling (struct loop *first_loop,
struct loop *second_loop)
{
- basic_block loop1_exit_bb = first_loop->single_exit->dest;
+ basic_block loop1_exit_bb = single_exit (first_loop)->dest;
basic_block loop2_entry_bb = loop_preheader_edge (second_loop)->src;
basic_block loop1_entry_bb = loop_preheader_edge (first_loop)->src;
basic_block bb_before_first_loop;
basic_block bb_between_loops;
basic_block new_exit_bb;
- edge exit_e = loop->single_exit;
+ edge exit_e = single_exit (loop);
LOC loop_loc;
if (!slpeel_can_duplicate_loop_p (loop, e))
*/
bb_before_first_loop = split_edge (loop_preheader_edge (first_loop));
- bb_before_second_loop = split_edge (first_loop->single_exit);
+ bb_before_second_loop = split_edge (single_exit (first_loop));
pre_condition =
fold_build2 (LE_EXPR, boolean_type_node, first_niters,
*/
bb_between_loops = new_exit_bb;
- bb_after_second_loop = split_edge (second_loop->single_exit);
+ bb_after_second_loop = split_edge (single_exit (second_loop));
pre_condition =
fold_build2 (EQ_EXPR, boolean_type_node, first_niters, niters);