If a loop's header count is less than iteration count, the iteration estimation is apparently incorrect for this loop. Thus disable unrolling of such loops.
Testing on going. OK for trunk if test pass? Thanks, Dehao gcc/ChangeLog: 2014-05-21 Dehao Chen <de...@google.com> * cfgloop.h (expected_loop_iterations_reliable_p): New func. * cfgloopanal.c (expected_loop_iterations_reliable_p): Likewise. * loop-unroll.c (decide_unroll_runtime_iterations): Disable unroll loop that has unreliable iteration counts. Index: gcc/cfgloop.h =================================================================== --- gcc/cfgloop.h (revision 210717) +++ gcc/cfgloop.h (working copy) @@ -307,8 +307,8 @@ extern bool just_once_each_iteration_p (const stru gcov_type expected_loop_iterations_unbounded (const struct loop *); extern unsigned expected_loop_iterations (const struct loop *); extern rtx doloop_condition_get (rtx); +extern bool expected_loop_iterations_reliable_p (const struct loop *); - /* Loop manipulation. */ extern bool can_duplicate_loop_p (const struct loop *loop); Index: gcc/cfgloopanal.c =================================================================== --- gcc/cfgloopanal.c (revision 210717) +++ gcc/cfgloopanal.c (working copy) @@ -285,6 +285,15 @@ expected_loop_iterations (const struct loop *loop) return (expected > REG_BR_PROB_BASE ? REG_BR_PROB_BASE : expected); } +/* Returns true if the loop header's profile count is smaller than expected + loop iteration. */ + +bool +expected_loop_iterations_reliable_p (const struct loop *loop) +{ + return expected_loop_iterations (loop) < loop->header->count; +} + /* Returns the maximum level of nesting of subloops of LOOP. */ unsigned Index: gcc/loop-unroll.c =================================================================== --- gcc/loop-unroll.c (revision 210717) +++ gcc/loop-unroll.c (working copy) @@ -988,6 +988,15 @@ decide_unroll_runtime_iterations (struct loop *loo return; } + if (profile_status_for_fn (cfun) == PROFILE_READ + && expected_loop_iterations_reliable_p (loop)) + { + if (dump_file) + fprintf (dump_file, ";; Not unrolling loop, loop iteration " + "not reliable."); + return; + } + /* Check whether the loop rolls. */ if ((get_estimated_loop_iterations (loop, &iterations) || get_max_loop_iterations (loop, &iterations))