X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcfgloopanal.c;h=129ec25a331bb0e6d260c790a85cb119f32c37ea;hb=fbb73d9bb6980aacb2366cbde38d255de0fde0fe;hp=13b674aaecbe32c5a29750bfdefda4e4c14db784;hpb=f24ec26f1cabb4f55cdb4370f35b67807df8fb7a;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index 13b674aaecb..129ec25a331 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -1,5 +1,6 @@ /* Natural loop analysis code for GNU compiler. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GCC. @@ -29,11 +30,12 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "output.h" #include "graphds.h" +#include "params.h" /* Checks whether BB is executed exactly once in each LOOP iteration. */ bool -just_once_each_iteration_p (const struct loop *loop, basic_block bb) +just_once_each_iteration_p (const struct loop *loop, const_basic_block bb) { /* It must be executed at least once each iteration. */ if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb)) @@ -50,26 +52,6 @@ just_once_each_iteration_p (const struct loop *loop, basic_block bb) return true; } -/* Marks the edge E in graph G irreducible if it connects two vertices in the - same scc. */ - -static void -check_irred (struct graph *g, struct graph_edge *e) -{ - edge real = (edge) e->data; - - /* All edges should lead from a component with higher number to the - one with lower one. */ - gcc_assert (g->vertices[e->src].component >= g->vertices[e->dest].component); - - if (g->vertices[e->src].component != g->vertices[e->dest].component) - return; - - real->flags |= EDGE_IRREDUCIBLE_LOOP; - if (flow_bb_inside_loop_p (real->src->loop_father, real->dest)) - real->src->flags |= BB_IRREDUCIBLE_LOOP; -} - /* Marks blocks and edges that are part of non-recognized loops; i.e. we throw away all latch edges and mark blocks inside any remaining cycle. Everything is a bit complicated due to fact we do not want to do this @@ -82,10 +64,11 @@ check_irred (struct graph *g, struct graph_edge *e) #define LOOP_REPR(LOOP) ((LOOP)->num + last_basic_block) #define BB_REPR(BB) ((BB)->index + 1) -void +bool mark_irreducible_loops (void) { basic_block act; + struct graph_edge *ge; edge e; edge_iterator ei; int src, dest; @@ -93,6 +76,8 @@ mark_irreducible_loops (void) struct graph *g; int num = number_of_loops (); struct loop *cloop; + bool irred_loop_found = false; + int i; gcc_assert (current_loops != NULL); @@ -152,16 +137,35 @@ mark_irreducible_loops (void) graphds_scc (g, NULL); /* Mark the irreducible loops. */ - for_each_edge (g, check_irred); + for (i = 0; i < g->n_vertices; i++) + for (ge = g->vertices[i].succ; ge; ge = ge->succ_next) + { + edge real = (edge) ge->data; + /* edge E in graph G is irreducible if it connects two vertices in the + same scc. */ + + /* All edges should lead from a component with higher number to the + one with lower one. */ + gcc_assert (g->vertices[ge->src].component >= g->vertices[ge->dest].component); + + if (g->vertices[ge->src].component != g->vertices[ge->dest].component) + continue; + + real->flags |= EDGE_IRREDUCIBLE_LOOP; + irred_loop_found = true; + if (flow_bb_inside_loop_p (real->src->loop_father, real->dest)) + real->src->flags |= BB_IRREDUCIBLE_LOOP; + } free_graph (g); loops_state_set (LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS); + return irred_loop_found; } /* Counts number of insns inside LOOP. */ int -num_loop_insns (struct loop *loop) +num_loop_insns (const struct loop *loop) { basic_block *bbs, bb; unsigned i, ninsns = 0; @@ -171,19 +175,21 @@ num_loop_insns (struct loop *loop) for (i = 0; i < loop->num_nodes; i++) { bb = bbs[i]; - ninsns++; - for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn)) - if (INSN_P (insn)) + FOR_BB_INSNS (bb, insn) + if (NONDEBUG_INSN_P (insn)) ninsns++; } - free(bbs); + free (bbs); + + if (!ninsns) + ninsns = 1; /* To avoid division by zero. */ return ninsns; } /* Counts number of insns executed on average per iteration LOOP. */ int -average_num_loop_insns (struct loop *loop) +average_num_loop_insns (const struct loop *loop) { basic_block *bbs, bb; unsigned i, binsns, ninsns, ratio; @@ -195,9 +201,9 @@ average_num_loop_insns (struct loop *loop) { bb = bbs[i]; - binsns = 1; - for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn)) - if (INSN_P (insn)) + binsns = 0; + FOR_BB_INSNS (bb, insn) + if (NONDEBUG_INSN_P (insn)) binsns++; ratio = loop->header->frequency == 0 @@ -205,7 +211,7 @@ average_num_loop_insns (struct loop *loop) : (bb->frequency * BB_FREQ_MAX) / loop->header->frequency; ninsns += binsns * ratio; } - free(bbs); + free (bbs); ninsns /= BB_FREQ_MAX; if (!ninsns) @@ -294,7 +300,7 @@ get_loop_level (const struct loop *loop) /* Returns estimate on cost of computing SEQ. */ static unsigned -seq_cost (rtx seq) +seq_cost (const_rtx seq, bool speed) { unsigned cost = 0; rtx set; @@ -303,7 +309,7 @@ seq_cost (rtx seq) { set = single_set (seq); if (set) - cost += rtx_cost (set, SET); + cost += rtx_cost (set, SET, speed); else cost++; } @@ -316,10 +322,10 @@ seq_cost (rtx seq) unsigned target_avail_regs; /* Number of available registers. */ unsigned target_res_regs; /* Number of registers reserved for temporary expressions. */ -unsigned target_reg_cost; /* The cost for register when there still +unsigned target_reg_cost[2]; /* The cost for register when there still is some reserve, but we are approaching the number of available registers. */ -unsigned target_spill_cost; /* The cost for register when we need +unsigned target_spill_cost[2]; /* The cost for register when we need to spill. */ /* Initialize the constants for computing set costs. */ @@ -327,6 +333,7 @@ unsigned target_spill_cost; /* The cost for register when we need void init_set_costs (void) { + int speed; rtx seq; rtx reg1 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER); rtx reg2 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER + 1); @@ -334,6 +341,7 @@ init_set_costs (void) rtx mem = validize_mem (gen_rtx_MEM (SImode, addr)); unsigned i; + target_avail_regs = 0; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i) && !fixed_regs[i]) @@ -341,27 +349,32 @@ init_set_costs (void) target_res_regs = 3; - /* Set up the costs for using extra registers: - - 1) If not many free registers remain, we should prefer having an - additional move to decreasing the number of available registers. - (TARGET_REG_COST). - 2) If no registers are available, we need to spill, which may require - storing the old value to memory and loading it back - (TARGET_SPILL_COST). */ - - start_sequence (); - emit_move_insn (reg1, reg2); - seq = get_insns (); - end_sequence (); - target_reg_cost = seq_cost (seq); - - start_sequence (); - emit_move_insn (mem, reg1); - emit_move_insn (reg2, mem); - seq = get_insns (); - end_sequence (); - target_spill_cost = seq_cost (seq); + for (speed = 0; speed < 2; speed++) + { + crtl->maybe_hot_insn_p = speed; + /* Set up the costs for using extra registers: + + 1) If not many free registers remain, we should prefer having an + additional move to decreasing the number of available registers. + (TARGET_REG_COST). + 2) If no registers are available, we need to spill, which may require + storing the old value to memory and loading it back + (TARGET_SPILL_COST). */ + + start_sequence (); + emit_move_insn (reg1, reg2); + seq = get_insns (); + end_sequence (); + target_reg_cost [speed] = seq_cost (seq, speed); + + start_sequence (); + emit_move_insn (mem, reg1); + emit_move_insn (reg2, mem); + seq = get_insns (); + end_sequence (); + target_spill_cost [speed] = seq_cost (seq, speed); + } + default_rtl_profile (); } /* Estimates cost of increased register pressure caused by making N_NEW new @@ -369,8 +382,9 @@ init_set_costs (void) around the loop. */ unsigned -estimate_reg_pressure_cost (unsigned n_new, unsigned n_old) +estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed) { + unsigned cost; unsigned regs_needed = n_new + n_old; /* If we have enough registers, we should use them and not restrict @@ -378,12 +392,25 @@ estimate_reg_pressure_cost (unsigned n_new, unsigned n_old) if (regs_needed + target_res_regs <= target_avail_regs) return 0; - /* If we are close to running out of registers, try to preserve them. */ if (regs_needed <= target_avail_regs) - return target_reg_cost * n_new; - - /* If we run out of registers, it is very expensive to add another one. */ - return target_spill_cost * n_new; + /* If we are close to running out of registers, try to preserve + them. */ + cost = target_reg_cost [speed] * n_new; + else + /* If we run out of registers, it is very expensive to add another + one. */ + cost = target_spill_cost [speed] * n_new; + + if (optimize && (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) + && number_of_loops () <= (unsigned) IRA_MAX_LOOPS_NUM) + /* IRA regional allocation deals with high register pressure + better. So decrease the cost (to do more accurate the cost + calculation for IRA, we need to know how many registers lives + through the loop transparently). */ + cost /= 2; + + return cost; } /* Sets EDGE_LOOP_EXIT flag for all loop exits. */