Hi, this patch makes expected_loop_iterations to be bit saner in coner cases. First expected_loop_iterations currently return 0 when -fguess-branch-probabiliteis is off and also in case the frequencies are downscaled to 0. Originally the function was intended to be used only for loops with profile computed, but this is not current practice so it is better to do something at least resonably sane. The patch makes expected_loop_iterations_unbounded to guess 3 iterations which is about the avreage number of iterations of a given loop in program.
On the other hand it may return bigger values than maximal number of iterations which we now have readily available from loop infrastructure. So it is good idea to cap the value by this. This makes updates after loop unrolling and similar transformations more sane. Bootstrapped/regtested x86_64-linux, will commit it shortly. Honza * cfgloop.h (expected_loop_iterations_unbounded, expected_loop_iterations): Unconstify. * cfgloopanal.c (expected_loop_iterations_unbounded): Sanity check the profile with known upper bound; return 3 when profile is absent. (expected_loop_iterations): Update. Index: cfgloop.h =================================================================== --- cfgloop.h (revision 236507) +++ cfgloop.h (working copy) @@ -316,8 +316,8 @@ extern void verify_loop_structure (void) /* Loop analysis. */ extern bool just_once_each_iteration_p (const struct loop *, const_basic_block); -gcov_type expected_loop_iterations_unbounded (const struct loop *); -extern unsigned expected_loop_iterations (const struct loop *); +gcov_type expected_loop_iterations_unbounded (struct loop *); +extern unsigned expected_loop_iterations (struct loop *); extern rtx doloop_condition_get (rtx); void mark_loop_for_removal (loop_p); Index: cfgloopanal.c =================================================================== --- cfgloopanal.c (revision 236507) +++ cfgloopanal.c (working copy) @@ -231,14 +231,20 @@ average_num_loop_insns (const struct loo value. */ gcov_type -expected_loop_iterations_unbounded (const struct loop *loop) +expected_loop_iterations_unbounded (struct loop *loop) { edge e; edge_iterator ei; + gcov_type expected; + - if (loop->latch->count || loop->header->count) + /* Average loop rolls about 3 times. If we have no profile at all, it is + best we can do. */ + if (profile_status_for_fn (cfun) == PROFILE_ABSENT) + expected = 3; + else if (loop->latch->count || loop->header->count) { - gcov_type count_in, count_latch, expected; + gcov_type count_in, count_latch; count_in = 0; count_latch = 0; @@ -253,8 +259,6 @@ expected_loop_iterations_unbounded (cons expected = count_latch * 2; else expected = (count_latch + count_in - 1) / count_in; - - return expected; } else { @@ -270,17 +274,28 @@ expected_loop_iterations_unbounded (cons freq_in += EDGE_FREQUENCY (e); if (freq_in == 0) - return freq_latch * 2; - - return (freq_latch + freq_in - 1) / freq_in; + { + /* If we have no profile at all, expect 3 iterations. */ + if (!freq_latch) + expected = 3; + else + expected = freq_latch * 2; + } + else + expected = (freq_latch + freq_in - 1) / freq_in; } + + HOST_WIDE_INT max = get_max_loop_iterations_int (loop); + if (max != -1 && max < expected) + return max; + return expected; } /* Returns expected number of LOOP iterations. The returned value is bounded by REG_BR_PROB_BASE. */ unsigned -expected_loop_iterations (const struct loop *loop) +expected_loop_iterations (struct loop *loop) { gcov_type expected = expected_loop_iterations_unbounded (loop); return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected);