aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-loop-manip.c
diff options
context:
space:
mode:
authorBin Cheng <bin.cheng@arm.com>2017-02-27 10:20:36 +0000
committerBin Cheng <amker@gcc.gnu.org>2017-02-27 10:20:36 +0000
commit57fa080bf6c0ae01bf1643a87e72ca636bde0454 (patch)
treef43af4a14ba4560b5196a61c743280e98d08cc5a /gcc/tree-ssa-loop-manip.c
parent68b948d3ba7cee54ba9f03a5b04f505f9c7538ff (diff)
downloadgcc-57fa080bf6c0ae01bf1643a87e72ca636bde0454.zip
gcc-57fa080bf6c0ae01bf1643a87e72ca636bde0454.tar.gz
gcc-57fa080bf6c0ae01bf1643a87e72ca636bde0454.tar.bz2
re PR tree-optimization/77536 (Vectorizer not maintaining relationship of relative block frequencies in absence of real profile data)
PR tree-optimization/77536 * tree-ssa-loop-manip.c (niter_for_unrolled_loop): New function. (tree_transform_and_unroll_loop): Use above function to compute the estimated niter of unrolled loop and use it when scaling profile. Also use count info rather than frequency if it's non-zero. * tree-ssa-loop-manip.h niter_for_unrolled_loop(): New declaration. * tree-vect-loop.c (scale_profile_for_vect_loop): New function. (vect_transform_loop): Call above function. gcc/testsuite * gcc.dg/vect/pr79347.c: Revise testing string. From-SVN: r245754
Diffstat (limited to 'gcc/tree-ssa-loop-manip.c')
-rw-r--r--gcc/tree-ssa-loop-manip.c70
1 files changed, 48 insertions, 22 deletions
diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c
index 43df29c..22c832a 100644
--- a/gcc/tree-ssa-loop-manip.c
+++ b/gcc/tree-ssa-loop-manip.c
@@ -1093,6 +1093,33 @@ scale_dominated_blocks_in_loop (struct loop *loop, basic_block bb,
}
}
+/* Return estimated niter for LOOP after unrolling by FACTOR times. */
+
+gcov_type
+niter_for_unrolled_loop (struct loop *loop, unsigned factor)
+{
+ gcc_assert (factor != 0);
+ bool profile_p = false;
+ gcov_type est_niter = expected_loop_iterations_unbounded (loop, &profile_p);
+ gcov_type new_est_niter = est_niter / factor;
+
+ /* Without profile feedback, loops for which we do not know a better estimate
+ are assumed to roll 10 times. When we unroll such loop, it appears to
+ roll too little, and it may even seem to be cold. To avoid this, we
+ ensure that the created loop appears to roll at least 5 times (but at
+ most as many times as before unrolling). Don't do adjustment if profile
+ feedback is present. */
+ if (new_est_niter < 5 && !profile_p)
+ {
+ if (est_niter < 5)
+ new_est_niter = est_niter;
+ else
+ new_est_niter = 5;
+ }
+
+ return new_est_niter;
+}
+
/* Unroll LOOP FACTOR times. DESC describes number of iterations of LOOP.
EXIT is the exit of the loop to that DESC corresponds.
@@ -1170,12 +1197,12 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
gimple_stmt_iterator bsi;
use_operand_p op;
bool ok;
- unsigned est_niter, prob_entry, scale_unrolled, scale_rest, freq_e, freq_h;
- unsigned new_est_niter, i, prob;
+ unsigned i, prob, prob_entry, scale_unrolled, scale_rest;
+ gcov_type freq_e, freq_h;
+ gcov_type new_est_niter = niter_for_unrolled_loop (loop, factor);
unsigned irr = loop_preheader_edge (loop)->flags & EDGE_IRREDUCIBLE_LOOP;
auto_vec<edge> to_remove;
- est_niter = expected_loop_iterations (loop);
determine_exit_conditions (loop, desc, factor,
&enter_main_cond, &exit_base, &exit_step,
&exit_cmp, &exit_bound);
@@ -1207,22 +1234,6 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
gcc_assert (new_loop != NULL);
update_ssa (TODO_update_ssa);
- /* Determine the probability of the exit edge of the unrolled loop. */
- new_est_niter = est_niter / factor;
-
- /* Without profile feedback, loops for that we do not know a better estimate
- are assumed to roll 10 times. When we unroll such loop, it appears to
- roll too little, and it may even seem to be cold. To avoid this, we
- ensure that the created loop appears to roll at least 5 times (but at
- most as many times as before unrolling). */
- if (new_est_niter < 5)
- {
- if (est_niter < 5)
- new_est_niter = est_niter;
- else
- new_est_niter = 5;
- }
-
/* Prepare the cfg and update the phi nodes. Move the loop exit to the
loop latch (and make its condition dummy, for the moment). */
rest = loop_preheader_edge (new_loop)->src;
@@ -1326,10 +1337,25 @@ tree_transform_and_unroll_loop (struct loop *loop, unsigned factor,
/* Ensure that the frequencies in the loop match the new estimated
number of iterations, and change the probability of the new
exit edge. */
- freq_h = loop->header->frequency;
- freq_e = EDGE_FREQUENCY (loop_preheader_edge (loop));
+
+ freq_h = loop->header->count;
+ freq_e = (loop_preheader_edge (loop))->count;
+ /* Use frequency only if counts are zero. */
+ if (freq_h == 0 && freq_e == 0)
+ {
+ freq_h = loop->header->frequency;
+ freq_e = EDGE_FREQUENCY (loop_preheader_edge (loop));
+ }
if (freq_h != 0)
- scale_loop_frequencies (loop, freq_e * (new_est_niter + 1), freq_h);
+ {
+ gcov_type scale;
+ /* Avoid dropping loop body profile counter to 0 because of zero count
+ in loop's preheader. */
+ freq_e = MAX (freq_e, 1);
+ /* This should not overflow. */
+ scale = GCOV_COMPUTE_SCALE (freq_e * (new_est_niter + 1), freq_h);
+ scale_loop_frequencies (loop, scale, REG_BR_PROB_BASE);
+ }
exit_bb = single_pred (loop->latch);
new_exit = find_edge (exit_bb, rest);