summaryrefslogtreecommitdiff
path: root/gcc/cfghooks.c
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-12 17:57:40 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-12 17:57:40 +0000
commitdce58e66ae4584a9832bccb103a155df58be9806 (patch)
tree6cc0ea65afc6e5ab5c27890dd53712843ef3bc17 /gcc/cfghooks.c
parent2656a84c1153d7b11ea2524305a8f5b9f66b17a6 (diff)
downloadgcc-dce58e66ae4584a9832bccb103a155df58be9806.tar.gz
* doc/loop.texi: Document recording of loop exits.
* cfgloopmanip.c (loopify, duplicate_loop): Use alloc_loop. (update_single_exits_after_duplication, update_single_exit_for_duplicated_loop, update_single_exit_for_duplicated_loops): Removed. (duplicate_loop_to_header_edge): Do not call update_single_exits_after_duplication and update_single_exit_for_duplicated_loops. (loop_version): Do not update single_exit information. (fix_loop_structure): Use record_loop_exits instead of mark_single_exit_loops. * tree-ssa-loop-manip.c (tree_transform_and_unroll_loop): Update the lists of loop exits. * cfghooks.c (redirect_edge_and_branch, redirect_edge_and_branch_force, split_edge, merge_blocks): Update the lists of loop exits. * modulo-sched.c (sms_schedule): Pass LOOPS_HAVE_RECORDED_EXITS to loop_optimizer_init. * loop-init.c (loop_optimizer_init): Call record_loop_exits instead of mark_single_exit_loops. (loop_optimizer_finalize): Call release_recorded_exits. * tree-ssa-loop.c (tree_loop_optimizer_init): Pass LOOPS_HAVE_RECORDED_EXITS to loop_optimizer_init. * tree-vectorizer.c (slpeel_tree_duplicate_loop_to_edge_cfg): Do not update single exit information. * lambda-code.c (perfect_nestify): Ditto. * cfgloop.c (flow_loop_free): Destroy the list of exits of the loop. (mark_single_exit_loops): Removed. (alloc_loop, loop_exit_hash, loop_exit_eq, loop_exit_free, get_exit_descriptions, rescan_loop_exit, record_loop_exits, dump_recorded_exit, dump_recorded_exits, release_recorded_exits): New functions. (get_loop_exit_edges, single_exit): Use recorded exit lists. (add_bb_to_loop, remove_bb_from_loops): Update the lists of loop exits. (verify_loop_structure): Verify consistency of the exit lists. (flow_loops_find): Use alloc_loop. Initialize exits hash. (set_single_exit): Removed. * cfgloop.h (struct loop_exit): New function. (struct loop): single_exit_ field replaced by exits field. (LOOPS_HAVE_MARKED_SINGLE_EXITS): Replaced by LOOPS_HAVE_RECORDED_EXITS. (struct loops): Added exits hash. (mark_single_exit_loops, set_single_exit): Declaration removed. (release_recorded_exits, record_loop_exits, rescan_loop_exit): Declare. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120728 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cfghooks.c')
-rw-r--r--gcc/cfghooks.c38
1 files changed, 31 insertions, 7 deletions
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index 50aca9f1b69..d6a981d1db8 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -310,6 +310,11 @@ redirect_edge_and_branch (edge e, basic_block dest)
ret = cfg_hooks->redirect_edge_and_branch (e, dest);
+ /* If RET != E, then the edge E was removed since RET already lead to the
+ same destination. */
+ if (ret != NULL && current_loops != NULL)
+ rescan_loop_exit (e, false, ret != e);
+
return ret;
}
@@ -320,19 +325,27 @@ redirect_edge_and_branch (edge e, basic_block dest)
basic_block
redirect_edge_and_branch_force (edge e, basic_block dest)
{
- basic_block ret;
+ basic_block ret, src = e->src;
struct loop *loop;
if (!cfg_hooks->redirect_edge_and_branch_force)
internal_error ("%s does not support redirect_edge_and_branch_force",
cfg_hooks->name);
+ if (current_loops != NULL)
+ rescan_loop_exit (e, false, true);
+
ret = cfg_hooks->redirect_edge_and_branch_force (e, dest);
- if (current_loops != NULL && ret != NULL)
+ if (current_loops != NULL)
{
- loop = find_common_loop (single_pred (ret)->loop_father,
- single_succ (ret)->loop_father);
- add_bb_to_loop (ret, loop);
+ if (ret != NULL)
+ {
+ loop = find_common_loop (single_pred (ret)->loop_father,
+ single_succ (ret)->loop_father);
+ add_bb_to_loop (ret, loop);
+ }
+ else if (find_edge (src, dest) == e)
+ rescan_loop_exit (e, true, false);
}
return ret;
@@ -452,6 +465,9 @@ split_edge (edge e)
if (!cfg_hooks->split_edge)
internal_error ("%s does not support split_edge", cfg_hooks->name);
+ if (current_loops != NULL)
+ rescan_loop_exit (e, false, true);
+
ret = cfg_hooks->split_edge (e);
ret->count = count;
ret->frequency = freq;
@@ -595,11 +611,19 @@ merge_blocks (basic_block a, basic_block b)
whole lot of them and hope the caller knows what they're doing. */
while (EDGE_COUNT (a->succs) != 0)
- remove_edge (EDGE_SUCC (a, 0));
+ {
+ if (current_loops != NULL)
+ rescan_loop_exit (EDGE_SUCC (a, 0), false, true);
+ remove_edge (EDGE_SUCC (a, 0));
+ }
/* Adjust the edges out of B for the new owner. */
FOR_EACH_EDGE (e, ei, b->succs)
- e->src = a;
+ {
+ e->src = a;
+ if (current_loops != NULL)
+ rescan_loop_exit (e, true, false);
+ }
a->succs = b->succs;
a->flags |= b->flags;