Patchwork Fix my change to unroll_loop_constant_iterations

login
register
mail settings
Submitter Jan Hubicka
Date Oct. 9, 2012, 1:12 p.m.
Message ID <20121009131200.GA20979@kam.mff.cuni.cz>
Download mbox | patch
Permalink /patch/190296/
State New
Headers show

Comments

Jan Hubicka - Oct. 9, 2012, 1:12 p.m.
Hi,
this is patch I comitted after checking, double checking and tripple checking.
I tested the patch on x86_64-linux. Unfortunately -O3 -fpeel-loops
-funroll-loops bootstrap still fails for me (-O3 bootstrap works), but it seems
independent problem - i.e. it fails with the change reverted, too.  I am
looking into it now.

I apologize for the breakage, I got completely sidetracked with the double_int
changes since I sort of missed the point that double_int has not signed nor
unsigned.

The patch fixes existing bug in overflow while computing iterations + 1 in
peeling decision. This exists on quite few releases and can trigger pointless
peeling of loops that iterate HOST_WIDE_INT_MAX times.

Honza

	* loop-unroll.c (unroll_loop_constant_iterations): Add
	update of loop->nb_iterations_upper_bound I missed in my previous
	commit; use TRUNC_DIV_EXPR instead of FLOOR_DIV_EXPR to divide
	iteration count.
	(decide_unroll_runtime_iterations): Avoid overflow.
	(unroll_loop_runtime_iterations): Use TRUNC_DIV_EXPR instead of
	FLOOR_DIV_EXPR to update iteration bounds.
	(decide_peel_simple): Avoid integer overflow when deciding
	on number of peelings.
	(decide_unroll_stupid): Likewise.

Patch

Index: loop-unroll.c
===================================================================
--- loop-unroll.c	(revision 192240)
+++ loop-unroll.c	(working copy)
@@ -740,6 +740,7 @@  unroll_loop_constant_iterations (struct
   	    apply_opt_in_copies (opt_info, exit_mod + 1, false, false);
 
 	  desc->niter -= exit_mod + 1;
+	  loop->nb_iterations_upper_bound -= double_int::from_uhwi (exit_mod + 1);
 	  if (loop->any_estimate
 	      && double_int::from_uhwi (exit_mod + 1).ule
 	           (loop->nb_iterations_estimate))
@@ -795,14 +796,14 @@  unroll_loop_constant_iterations (struct
 
   desc->niter /= max_unroll + 1;
   loop->nb_iterations_upper_bound
-    = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (exit_mod
+    = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (max_unroll
 								   + 1),
-					    FLOOR_DIV_EXPR);
+					    TRUNC_DIV_EXPR);
   if (loop->any_estimate)
     loop->nb_iterations_estimate
-      = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (exit_mod
+      = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (max_unroll
 							          + 1),
-				           FLOOR_DIV_EXPR);
+				           TRUNC_DIV_EXPR);
   desc->niter_expr = GEN_INT (desc->niter);
 
   /* Remove the edges.  */
@@ -876,11 +877,10 @@  decide_unroll_runtime_iterations (struct
       return;
     }
 
-  /* If we have profile feedback, check whether the loop rolls.  */
+  /* Check whether the loop rolls.  */
   if ((estimated_loop_iterations (loop, &iterations)
        || max_loop_iterations (loop, &iterations))
-      && iterations.fits_shwi ()
-      && iterations.to_shwi () <= 2 * nunroll)
+      && iterations.ult (double_int::from_shwi (2 * nunroll)))
     {
       if (dump_file)
 	fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");
@@ -1199,12 +1199,12 @@  unroll_loop_runtime_iterations (struct l
   loop->nb_iterations_upper_bound
     = loop->nb_iterations_upper_bound.udiv (double_int::from_uhwi (max_unroll
 								   + 1),
-					    FLOOR_DIV_EXPR);
+					    TRUNC_DIV_EXPR);
   if (loop->any_estimate)
     loop->nb_iterations_estimate
       = loop->nb_iterations_estimate.udiv (double_int::from_uhwi (max_unroll
 							          + 1),
-				           FLOOR_DIV_EXPR);
+				           TRUNC_DIV_EXPR);
   if (exit_at_end)
     {
       desc->niter_expr =
@@ -1280,8 +1280,7 @@  decide_peel_simple (struct loop *loop, i
   /* If we have realistic estimate on number of iterations, use it.  */
   if (estimated_loop_iterations (loop, &iterations))
     {
-      if (!iterations.fits_shwi ()
-	  || iterations.to_shwi () + 1 > npeel)
+      if (double_int::from_shwi (npeel).ule (iterations))
 	{
 	  if (dump_file)
 	    {
@@ -1298,8 +1297,7 @@  decide_peel_simple (struct loop *loop, i
   /* If we have small enough bound on iterations, we can still peel (completely
      unroll).  */
   else if (max_loop_iterations (loop, &iterations)
-           && iterations.fits_shwi ()
-           && iterations.to_shwi () + 1 <= npeel)
+           && iterations.ult (double_int::from_shwi (npeel)))
     npeel = iterations.to_shwi () + 1;
   else
     {
@@ -1446,11 +1444,10 @@  decide_unroll_stupid (struct loop *loop,
       return;
     }
 
-  /* If we have profile feedback, check whether the loop rolls.  */
+  /* Check whether the loop rolls.  */
   if ((estimated_loop_iterations (loop, &iterations)
        || max_loop_iterations (loop, &iterations))
-      && iterations.fits_shwi ()
-      && iterations.to_shwi () <= 2 * nunroll)
+      && iterations.ult (double_int::from_shwi (2 * nunroll)))
     {
       if (dump_file)
 	fprintf (dump_file, ";; Not unrolling loop, doesn't roll\n");