diff options
author | Jan Hubicka <jh@suse.cz> | 2012-09-30 17:30:22 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2012-09-30 15:30:22 +0000 |
commit | 6e73e84beed7b879e9c25b3570f10ce6f5a0630b (patch) | |
tree | 24b888e5a807be55e84069a80be6911f847d0451 /gcc/cfgloopmanip.c | |
parent | 78b0551a68d1a7e60e549a4852fe78e600ce5320 (diff) | |
download | gcc-6e73e84beed7b879e9c25b3570f10ce6f5a0630b.zip gcc-6e73e84beed7b879e9c25b3570f10ce6f5a0630b.tar.gz gcc-6e73e84beed7b879e9c25b3570f10ce6f5a0630b.tar.bz2 |
cfgloop.c (scale_loop_profile): Move to...
* cfgloop.c (scale_loop_profile): Move to...
* cfgloopmanip.c (scale_loop_profile): .. here; use
scale_loop_frequencies.
(loopify): Use RDIV.
From-SVN: r191868
Diffstat (limited to 'gcc/cfgloopmanip.c')
-rw-r--r-- | gcc/cfgloopmanip.c | 112 |
1 files changed, 109 insertions, 3 deletions
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index d84a56d..8a44a0b 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -39,8 +39,6 @@ static bool fix_bb_placement (basic_block); static void fix_bb_placements (basic_block, bool *); static void unloop (struct loop *, bool *); -#define RDIV(X,Y) (((X) + (Y) / 2) / (Y)) - /* Checks whether basic block BB is dominated by DATA. */ static bool rpe_enum_p (const_basic_block bb, const void *data) @@ -462,6 +460,7 @@ add_loop (struct loop *loop, struct loop *outer) } /* Multiply all frequencies in LOOP by NUM/DEN. */ + void scale_loop_frequencies (struct loop *loop, int num, int den) { @@ -472,6 +471,113 @@ scale_loop_frequencies (struct loop *loop, int num, int den) free (bbs); } +/* Multiply all frequencies in LOOP by SCALE/REG_BR_PROB_BASE. + If ITERATION_BOUND is non-zero, scale even further if loop is predicted + to iterate too many times. */ + +void +scale_loop_profile (struct loop *loop, int scale, int iteration_bound) +{ + gcov_type iterations = expected_loop_iterations_unbounded (loop); + edge e; + edge_iterator ei; + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, ";; Scaling loop %i with scale %f, " + "bounding iterations to %i from guessed %i\n", + loop->num, (double)scale / REG_BR_PROB_BASE, + iteration_bound, (int)iterations); + + /* See if loop is predicted to iterate too many times. */ + if (iteration_bound && iterations > 0 + && RDIV (iterations * scale, REG_BR_PROB_BASE) > iteration_bound) + { + /* Fixing loop profile for different trip count is not trivial; the exit + probabilities has to be updated to match and frequencies propagated down + to the loop body. + + We fully update only the simple case of loop with single exit that is + either from the latch or BB just before latch and leads from BB with + simple conditional jump. This is OK for use in vectorizer. */ + e = single_exit (loop); + if (e) + { + edge other_e; + int freq_delta; + gcov_type count_delta; + + FOR_EACH_EDGE (other_e, ei, e->src->succs) + if (!(other_e->flags & (EDGE_ABNORMAL | EDGE_FAKE)) + && e != other_e) + break; + + /* Probability of exit must be 1/iterations. */ + freq_delta = EDGE_FREQUENCY (e); + e->probability = REG_BR_PROB_BASE / iteration_bound; + other_e->probability = inverse_probability (e->probability); + freq_delta -= EDGE_FREQUENCY (e); + + /* Adjust counts accordingly. */ + count_delta = e->count; + e->count = apply_probability (e->src->count, e->probability); + other_e->count = apply_probability (e->src->count, other_e->probability); + count_delta -= e->count; + + /* If latch exists, change its frequency and count, since we changed + probability of exit. Theoretically we should update everything from + source of exit edge to latch, but for vectorizer this is enough. */ + if (loop->latch + && loop->latch != e->src) + { + loop->latch->frequency += freq_delta; + if (loop->latch->frequency < 0) + loop->latch->frequency = 0; + loop->latch->count += count_delta; + if (loop->latch->count < 0) + loop->latch->count = 0; + } + } + + /* Roughly speaking we want to reduce the loop body profile by the + the difference of loop iterations. We however can do better if + we look at the actual profile, if it is available. */ + scale = RDIV (iteration_bound * scale, iterations); + if (loop->header->count) + { + gcov_type count_in = 0; + + FOR_EACH_EDGE (e, ei, loop->header->preds) + if (e->src != loop->latch) + count_in += e->count; + + if (count_in != 0) + scale = RDIV (count_in * iteration_bound * REG_BR_PROB_BASE, loop->header->count); + } + else if (loop->header->frequency) + { + int freq_in = 0; + + FOR_EACH_EDGE (e, ei, loop->header->preds) + if (e->src != loop->latch) + freq_in += EDGE_FREQUENCY (e); + + if (freq_in != 0) + scale = RDIV (freq_in * iteration_bound * REG_BR_PROB_BASE, loop->header->frequency); + } + if (!scale) + scale = 1; + } + + if (scale == REG_BR_PROB_BASE) + return; + + /* Scale the actual probabilities. */ + scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE); + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, ";; guessed iterations are now %i\n", + (int)expected_loop_iterations_unbounded (loop)); +} + /* Recompute dominance information for basic blocks outside LOOP. */ static void @@ -772,7 +878,7 @@ loopify (edge latch_edge, edge header_edge, switch_bb->count = cnt; FOR_EACH_EDGE (e, ei, switch_bb->succs) { - e->count = (switch_bb->count * e->probability) / REG_BR_PROB_BASE; + e->count = RDIV (switch_bb->count * e->probability, REG_BR_PROB_BASE); } } scale_loop_frequencies (loop, false_scale, REG_BR_PROB_BASE); |