This teaches loop-iv (RTL IV analysis) about loop->nb_iterations_upper_bound. It avoids poinless unrolling of vectorizer prologue loops for now.
Bootstrap and regtest pending on x86_64-unknown-linux-gnu. Richard. 2012-04-18 Richard Guenther <rguent...@suse.de> PR rtl-optimization/44688 * loop-iv.c (determine_max_iter): Only return max_iter. (iv_number_of_iterations): Also use the recorded loop bound on the maximum number of iterations. * loop-unroll.c (decide_unroll_runtime_iterations): Use max_iter to avoid unrolling loops that do not roll. (decide_unroll_stupid): Likewise. Index: gcc/loop-iv.c =================================================================== *** gcc/loop-iv.c.orig 2012-04-18 15:29:39.000000000 +0200 --- gcc/loop-iv.c 2012-04-18 16:03:21.911222247 +0200 *************** canonicalize_iv_subregs (struct rtx_iv * *** 2190,2197 **** return true; } ! /* Tries to estimate the maximum number of iterations in LOOP, and store the ! result in DESC. This function is called from iv_number_of_iterations with a number of fields in DESC already filled in. OLD_NITER is the original expression for the number of iterations, before we tried to simplify it. */ --- 2190,2197 ---- return true; } ! /* Tries to estimate the maximum number of iterations in LOOP, and return the ! result. This function is called from iv_number_of_iterations with a number of fields in DESC already filled in. OLD_NITER is the original expression for the number of iterations, before we tried to simplify it. */ *************** determine_max_iter (struct loop *loop, s *** 2207,2216 **** { nmax = INTVAL (XEXP (niter, 0)); if (!(nmax & (nmax + 1))) ! { ! desc->niter_max = nmax; ! return nmax; ! } } get_mode_bounds (desc->mode, desc->signed_p, desc->mode, &mmin, &mmax); --- 2207,2213 ---- { nmax = INTVAL (XEXP (niter, 0)); if (!(nmax & (nmax + 1))) ! return nmax; } get_mode_bounds (desc->mode, desc->signed_p, desc->mode, &mmin, &mmax); *************** determine_max_iter (struct loop *loop, s *** 2219,2228 **** if (GET_CODE (niter) == UDIV) { if (!CONST_INT_P (XEXP (niter, 1))) ! { ! desc->niter_max = nmax; ! return nmax; ! } inc = INTVAL (XEXP (niter, 1)); niter = XEXP (niter, 0); } --- 2216,2222 ---- if (GET_CODE (niter) == UDIV) { if (!CONST_INT_P (XEXP (niter, 1))) ! return nmax; inc = INTVAL (XEXP (niter, 1)); niter = XEXP (niter, 0); } *************** determine_max_iter (struct loop *loop, s *** 2241,2247 **** if (dump_file) fprintf (dump_file, ";; improved upper bound by one.\n"); } - desc->niter_max = nmax / inc; return nmax / inc; } --- 2235,2240 ---- *************** iv_number_of_iterations (struct loop *lo *** 2259,2265 **** enum rtx_code cond; enum machine_mode mode, comp_mode; rtx mmin, mmax, mode_mmin, mode_mmax; ! unsigned HOST_WIDEST_INT s, size, d, inv; HOST_WIDEST_INT up, down, inc, step_val; int was_sharp = false; rtx old_niter; --- 2252,2258 ---- enum rtx_code cond; enum machine_mode mode, comp_mode; rtx mmin, mmax, mode_mmin, mode_mmax; ! unsigned HOST_WIDEST_INT s, size, d, inv, max; HOST_WIDEST_INT up, down, inc, step_val; int was_sharp = false; rtx old_niter; *************** iv_number_of_iterations (struct loop *lo *** 2279,2284 **** --- 2272,2280 ---- desc->const_iter = false; desc->niter_expr = NULL_RTX; desc->niter_max = 0; + if (loop->any_upper_bound + && double_int_fits_in_uhwi_p (loop->nb_iterations_upper_bound)) + desc->niter_max = loop->nb_iterations_upper_bound.low; cond = GET_CODE (condition); gcc_assert (COMPARISON_P (condition)); *************** iv_number_of_iterations (struct loop *lo *** 2547,2553 **** down = INTVAL (CONST_INT_P (iv0.base) ? iv0.base : mode_mmin); ! desc->niter_max = (up - down) / inc + 1; if (iv0.step == const0_rtx) { --- 2543,2552 ---- down = INTVAL (CONST_INT_P (iv0.base) ? iv0.base : mode_mmin); ! max = (up - down) / inc + 1; ! if (!desc->niter_max ! || max < desc->niter_max) ! desc->niter_max = max; if (iv0.step == const0_rtx) { *************** iv_number_of_iterations (struct loop *lo *** 2762,2769 **** } else { ! if (!desc->niter_max) ! desc->niter_max = determine_max_iter (loop, desc, old_niter); /* simplify_using_initial_values does a copy propagation on the registers in the expression for the number of iterations. This prolongs life --- 2761,2770 ---- } else { ! max = determine_max_iter (loop, desc, old_niter); ! if (!desc->niter_max ! || max < desc->niter_max) ! desc->niter_max = max; /* simplify_using_initial_values does a copy propagation on the registers in the expression for the number of iterations. This prolongs life Index: gcc/loop-unroll.c =================================================================== *** gcc/loop-unroll.c.orig 2012-04-18 15:29:39.000000000 +0200 --- gcc/loop-unroll.c 2012-04-18 16:10:24.444196989 +0200 *************** decide_unroll_runtime_iterations (struct *** 857,863 **** } /* If we have profile feedback, check whether the loop rolls. */ ! if (loop->header->count && expected_loop_iterations (loop) < 2 * nunroll) { if (dump_file) fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n"); --- 857,865 ---- } /* If we have profile feedback, check whether the loop rolls. */ ! if ((loop->header->count ! && expected_loop_iterations (loop) < 2 * nunroll) ! || desc->niter_max < 2 * nunroll) { if (dump_file) fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n"); *************** decide_unroll_stupid (struct loop *loop, *** 1400,1407 **** } /* If we have profile feedback, check whether the loop rolls. */ ! if (loop->header->count ! && expected_loop_iterations (loop) < 2 * nunroll) { if (dump_file) fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n"); --- 1402,1410 ---- } /* If we have profile feedback, check whether the loop rolls. */ ! if ((loop->header->count ! && expected_loop_iterations (loop) < 2 * nunroll) ! || desc->niter_max < 2 * nunroll) { if (dump_file) fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");