X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcfgloopanal.c;h=5a9189787eae1727a0eac86b7e49dc5a23cdeda0;hb=99f2248e961ae8770af13ccd04282b83758500e5;hp=6c625d6a9741fec7fa916eef7ef45b27b34bde43;hpb=42fe97ed1a1d59a2d77f80a2823ec938a94ecc7b;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index 6c625d6a974..5a9189787ea 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -1,5 +1,5 @@ /* Natural loop analysis code for GNU compiler. - Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GCC. @@ -15,8 +15,8 @@ for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ +Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301, USA. */ #include "config.h" #include "system.h" @@ -33,7 +33,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* Checks whether BB is executed exactly once in each LOOP iteration. */ bool -just_once_each_iteration_p (struct loop *loop, basic_block bb) +just_once_each_iteration_p (const struct loop *loop, basic_block bb) { /* It must be executed at least once each iteration. */ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb)) @@ -83,7 +83,9 @@ struct graph /* Dumps graph G into F. */ extern void dump_graph (FILE *, struct graph *); -void dump_graph (FILE *f, struct graph *g) + +void +dump_graph (FILE *f, struct graph *g) { int i; struct edge *e; @@ -111,10 +113,10 @@ void dump_graph (FILE *f, struct graph *g) static struct graph * new_graph (int n_vertices) { - struct graph *g = xmalloc (sizeof (struct graph)); + struct graph *g = XNEW (struct graph); g->n_vertices = n_vertices; - g->vertices = xcalloc (n_vertices, sizeof (struct vertex)); + g->vertices = XCNEWVEC (struct vertex, n_vertices); return g; } @@ -178,7 +180,7 @@ dfs (struct graph *g, int *qs, int nq, int *qt, bool forward) { if (qt) qt[tick] = v; - g->vertices[v].post = tick++; + g->vertices[v].post = tick++; if (!top) break; @@ -257,24 +259,26 @@ free_graph (struct graph *g) for parts of cycles that only "pass" through some loop -- i.e. for each cycle, we want to mark blocks that belong directly to innermost loop containing the whole cycle. - + LOOPS is the loop tree. */ #define LOOP_REPR(LOOP) ((LOOP)->num + last_basic_block) #define BB_REPR(BB) ((BB)->index + 1) void -mark_irreducible_loops (struct loops *loops) +mark_irreducible_loops (void) { basic_block act; edge e; edge_iterator ei; int i, src, dest; struct graph *g; - int *queue1 = xmalloc ((last_basic_block + loops->num) * sizeof (int)); - int *queue2 = xmalloc ((last_basic_block + loops->num) * sizeof (int)); + int num = current_loops ? number_of_loops () : 1; + int *queue1 = XNEWVEC (int, last_basic_block + num); + int *queue2 = XNEWVEC (int, last_basic_block + num); int nq, depth; - struct loop *cloop; + struct loop *cloop, *loop; + loop_iterator li; /* Reset the flags. */ FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb) @@ -285,44 +289,47 @@ mark_irreducible_loops (struct loops *loops) } /* Create the edge lists. */ - g = new_graph (last_basic_block + loops->num); + g = new_graph (last_basic_block + num); FOR_BB_BETWEEN (act, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb) FOR_EACH_EDGE (e, ei, act->succs) { - /* Ignore edges to exit. */ - if (e->dest == EXIT_BLOCK_PTR) + /* Ignore edges to exit. */ + if (e->dest == EXIT_BLOCK_PTR) continue; - /* And latch edges. */ - if (e->dest->loop_father->header == e->dest - && e->dest->loop_father->latch == act) - continue; + src = BB_REPR (act); + dest = BB_REPR (e->dest); + + if (current_loops) + { + /* Ignore latch edges. */ + if (e->dest->loop_father->header == e->dest + && e->dest->loop_father->latch == act) + continue; - /* Edges inside a single loop should be left where they are. Edges - to subloop headers should lead to representative of the subloop, - but from the same place. + /* Edges inside a single loop should be left where they are. Edges + to subloop headers should lead to representative of the subloop, + but from the same place. - Edges exiting loops should lead from representative - of the son of nearest common ancestor of the loops in that - act lays. */ + Edges exiting loops should lead from representative + of the son of nearest common ancestor of the loops in that + act lays. */ - src = BB_REPR (act); - dest = BB_REPR (e->dest); + if (e->dest->loop_father->header == e->dest) + dest = LOOP_REPR (e->dest->loop_father); - if (e->dest->loop_father->header == e->dest) - dest = LOOP_REPR (e->dest->loop_father); + if (!flow_bb_inside_loop_p (act->loop_father, e->dest)) + { + depth = find_common_loop (act->loop_father, + e->dest->loop_father)->depth + 1; + if (depth == act->loop_father->depth) + cloop = act->loop_father; + else + cloop = act->loop_father->pred[depth]; - if (!flow_bb_inside_loop_p (act->loop_father, e->dest)) - { - depth = find_common_loop (act->loop_father, - e->dest->loop_father)->depth + 1; - if (depth == act->loop_father->depth) - cloop = act->loop_father; - else - cloop = act->loop_father->pred[depth]; - - src = LOOP_REPR (cloop); + src = LOOP_REPR (cloop); + } } add_edge (g, src, dest, e); @@ -337,9 +344,14 @@ mark_irreducible_loops (struct loops *loops) { queue1[nq++] = BB_REPR (act); } - for (i = 1; i < (int) loops->num; i++) - if (loops->parray[i]) - queue1[nq++] = LOOP_REPR (loops->parray[i]); + + if (current_loops) + { + FOR_EACH_LOOP (li, loop, 0) + { + queue1[nq++] = LOOP_REPR (loop); + } + } dfs (g, queue1, nq, queue2, false); for (i = 0; i < nq; i++) queue1[i] = queue2[nq - i - 1]; @@ -352,7 +364,8 @@ mark_irreducible_loops (struct loops *loops) free (queue1); free (queue2); - loops->state |= LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS; + if (current_loops) + current_loops->state |= LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS; } /* Counts number of insns inside LOOP. */ @@ -419,7 +432,7 @@ expected_loop_iterations (const struct loop *loop) edge e; edge_iterator ei; - if (loop->header->count) + if (loop->latch->count || loop->header->count) { gcov_type count_in, count_latch, expected; @@ -433,9 +446,9 @@ expected_loop_iterations (const struct loop *loop) count_in += e->count; if (count_in == 0) - expected = count_latch * 2; + expected = count_latch * 2; else - expected = (count_latch + count_in - 1) / count_in; + expected = (count_latch + count_in - 1) / count_in; /* Avoid overflows. */ return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected); @@ -526,7 +539,7 @@ init_set_costs (void) target_res_regs = 3; /* These are really just heuristic values. */ - + start_sequence (); emit_move_insn (reg1, reg2); seq = get_insns (); @@ -565,3 +578,29 @@ global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses) return cost; } +/* Sets EDGE_LOOP_EXIT flag for all loop exits. */ + +void +mark_loop_exit_edges (void) +{ + basic_block bb; + edge e; + + if (!current_loops) + return; + + FOR_EACH_BB (bb) + { + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) + { + if (bb->loop_father->outer + && loop_exit_edge_p (bb->loop_father, e)) + e->flags |= EDGE_LOOP_EXIT; + else + e->flags &= ~EDGE_LOOP_EXIT; + } + } +} +