summaryrefslogtreecommitdiff
path: root/gcc/cfgloopmanip.c
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-06 21:49:49 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-06 21:49:49 +0000
commit4a6f9e197c022b9b9efb396b6f13a2c2dbc2234f (patch)
tree0b2228e5e39d0218784f7e5f8304e2e94d0d96c2 /gcc/cfgloopmanip.c
parent0d8970e35cd11c6e895434af7ab691c1ebf0f4f4 (diff)
downloadgcc-4a6f9e197c022b9b9efb396b6f13a2c2dbc2234f.tar.gz
* doc/loop.texi: Document possibility not to perform disambiguation
of loops with multiple latches. * cfgloopmanip.c (alp_enum_p): Removed. (add_loop): Handle subloops. Use get_loop_body_with_size. (create_preheader): Do not allow ENTRY_BLOCK_PTR to be preheader. * cfghooks.c (redirect_edge_and_branch_force): Set dominator for the new forwarder block. (make_forwarder_block): Only call new_bb_cbk if it is not NULL. Handle the case latch is NULL. * tree-ssa-dom.c (tree_ssa_dominator_optimize): Avoid cfg modifications when marking loop exits. * ifcvt.c (if_convert): Ditto. Mark loop exits even if cfg cannot be modified. * loop-init.c (loop_optimizer_init): Do not modify cfg. Call disambiguate_loops_with_multiple_latches. * tree-cfgcleanup.c (cleanup_tree_cfg_loop): Calculate dominators before fix_loop_structure. * cfgloop.c: Include pointer-set.h and output.h. (canonicalize_loop_headers, HEADER_BLOCK, LATCH_EDGE, update_latch_info, mfb_keep_just, mfb_keep_nonlatch): Removed. (get_loop_latch_edges, find_subloop_latch_edge_by_profile, find_subloop_latch_edge_by_ivs, find_subloop_latch_edge, mfb_redirect_edges_in_set, form_subloop, merge_latch_edges, disambiguate_multiple_latches, get_loop_body_with_size, disambiguate_loops_with_multiple_latches): New functions. (flow_loop_dump): Dump multiple latch edges. (flow_loop_nodes_find): Handle loops with multiple latches. (flow_loops_find): Ditto. Do not call canonicalize_loop_headers. (glb_enum_p): Modified. (get_loop_body): Use get_loop_body_with_size. * cfgloop.h (LOOPS_HAVE_RECORDED_EXITS): New flag. (AVOID_CFG_MODIFICATIONS): New constant. (disambiguate_loops_with_multiple_latches, add_loop, get_loop_body_with_size): Declare. * Makefile.in (cfgloop.o): Add pointer-set.h and output.h. * gcc.dg/tree-ssa/loop-25.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121670 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cfgloopmanip.c')
-rw-r--r--gcc/cfgloopmanip.c64
1 files changed, 36 insertions, 28 deletions
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 8e5f4c2bf38..9ca3947a0c6 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -38,11 +38,9 @@ static void loop_redirect_edge (edge, basic_block);
static void remove_bbs (basic_block *, int);
static bool rpe_enum_p (basic_block, void *);
static int find_path (edge, basic_block **);
-static bool alp_enum_p (basic_block, void *);
static void fix_loop_placements (struct loop *, bool *);
static bool fix_bb_placement (basic_block);
static void fix_bb_placements (basic_block, bool *);
-static void place_new_loop (struct loop *);
static basic_block create_preheader (struct loop *, int);
static void unloop (struct loop *, bool *);
@@ -395,39 +393,54 @@ remove_path (edge e)
return true;
}
-/* Predicate for enumeration in add_loop. */
-static bool
-alp_enum_p (basic_block bb, void *alp_header)
+/* Creates place for a new LOOP in loops structure. */
+
+static void
+place_new_loop (struct loop *loop)
{
- return bb != (basic_block) alp_header;
+ loop->num = number_of_loops ();
+ VEC_safe_push (loop_p, heap, current_loops->larray, loop);
}
/* Given LOOP structure with filled header and latch, find the body of the
corresponding loop and add it to loops tree. Insert the LOOP as a son of
outer. */
-static void
+void
add_loop (struct loop *loop, struct loop *outer)
{
basic_block *bbs;
int i, n;
+ struct loop *subloop;
/* Add it to loop structure. */
place_new_loop (loop);
flow_loop_tree_node_add (outer, loop);
/* Find its nodes. */
- bbs = XCNEWVEC (basic_block, n_basic_blocks);
- n = dfs_enumerate_from (loop->latch, 1, alp_enum_p,
- bbs, n_basic_blocks, loop->header);
+ bbs = XNEWVEC (basic_block, n_basic_blocks);
+ n = get_loop_body_with_size (loop, bbs, n_basic_blocks);
for (i = 0; i < n; i++)
{
- remove_bb_from_loops (bbs[i]);
- add_bb_to_loop (bbs[i], loop);
+ if (bbs[i]->loop_father == outer)
+ {
+ remove_bb_from_loops (bbs[i]);
+ add_bb_to_loop (bbs[i], loop);
+ continue;
+ }
+
+ loop->num_nodes++;
+
+ /* If we find a direct subloop of OUTER, move it to LOOP. */
+ subloop = bbs[i]->loop_father;
+ if (subloop->outer == outer
+ && subloop->header == bbs[i])
+ {
+ flow_loop_tree_node_remove (subloop);
+ flow_loop_tree_node_add (loop, subloop);
+ }
}
- remove_bb_from_loops (loop->header);
- add_bb_to_loop (loop->header, loop);
free (bbs);
}
@@ -631,14 +644,6 @@ fix_loop_placements (struct loop *loop, bool *irred_invalidated)
}
}
-/* Creates place for a new LOOP in loops structure. */
-static void
-place_new_loop (struct loop *loop)
-{
- loop->num = number_of_loops ();
- VEC_safe_push (loop_p, heap, current_loops->larray, loop);
-}
-
/* Copies copy of LOOP as subloop of TARGET loop, placing newly
created loop into loops structure. */
struct loop *
@@ -1115,12 +1120,15 @@ create_preheader (struct loop *loop, int flags)
gcc_assert (nentry);
if (nentry == 1)
{
- /* Get an edge that is different from the one from loop->latch
- to loop->header. */
- e = EDGE_PRED (loop->header,
- EDGE_PRED (loop->header, 0)->src == loop->latch);
-
- if (!(flags & CP_SIMPLE_PREHEADERS) || single_succ_p (e->src))
+ e = loop_preheader_edge (loop);
+
+ if (/* We do not allow entry block to be the loop preheader, since we
+ cannot emit code there. */
+ e->src != ENTRY_BLOCK_PTR
+ /* If we want simple preheaders, also force the preheader to have
+ just a single successor. */
+ && !((flags & CP_SIMPLE_PREHEADERS)
+ && !single_succ_p (e->src)))
return NULL;
}