diff options
author | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-06 21:49:49 +0000 |
---|---|---|
committer | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-06 21:49:49 +0000 |
commit | 4a6f9e197c022b9b9efb396b6f13a2c2dbc2234f (patch) | |
tree | 0b2228e5e39d0218784f7e5f8304e2e94d0d96c2 /gcc/cfgloopmanip.c | |
parent | 0d8970e35cd11c6e895434af7ab691c1ebf0f4f4 (diff) | |
download | gcc-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.c | 64 |
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; } |