This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: optimization/8599: [3.2 regression] loop unroll bug with -march=k6-3


Hi Franz,

I think the correct fix is attached (pr8599-2.diff). It produces valid code on 
K6 at -O2 -funroll-loops in all cases and passed a complete cycle of 
bootstrapping/regtesting.

Could you test it on powerpc-linux-gnu (after reverting the first patch 
pr8599-1.diff) when you have some time ? Thanks in advance.

-- 
Eric Botcazou
Index: doloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doloop.c,v
retrieving revision 1.16.8.2
retrieving revision 1.16.8.3
diff -u -r1.16.8.2 -r1.16.8.3
--- doloop.c	26 Sep 2002 23:10:38 -0000	1.16.8.2
+++ doloop.c	22 Nov 2002 21:20:04 -0000	1.16.8.3
@@ -598,16 +598,19 @@
 
      If the loop has been unrolled, the full calculation is
 
-       t1 = abs_inc * unroll_number;		increment per loop
-       n = abs (final - initial) / t1;		full loops
-       n += (abs (final - initial) % t1) != 0;	partial loop
-
-     However, in certain cases the unrolled loop will be preconditioned
-     by emitting copies of the loop body with conditional branches,
-     so that the unrolled loop is always a full loop and thus needs
-     no exit tests.  In this case we don't want to add the partial
-     loop count.  As above, when t1 is a power of two we don't need to
-     worry about overflow.
+       t1 = abs_inc * unroll_number;		        increment per loop
+       n = (abs (final - initial) + abs_inc - 1) / t1;    full loops
+       n += (abs (final - initial) + abs_inc - 1) % t1) >= abs_inc;
+                                                          partial loop
+     which works out to be equivalent to
+
+       n = (abs (final - initial) + t1 - 1) / t1;
+
+     In the case where the loop was preconditioned, a few iterations
+     may have been executed earlier; but 'initial' was adjusted as they
+     were executed, so we don't need anything special for that case here.
+     As above, when t1 is a power of two we don't need to worry about
+     overflow.
 
      The division and modulo operations can be avoided by requiring
      that the increment is a power of 2 (precondition_loop_p enforces
@@ -682,10 +685,10 @@
       if (shift_count < 0)
 	abort ();
 
-      if (!loop_info->preconditioned)
-	diff = expand_simple_binop (GET_MODE (diff), PLUS,
-				    diff, GEN_INT (abs_loop_inc - 1),
-				    diff, 1, OPTAB_LIB_WIDEN);
+      /* (abs (final - initial) + abs_inc * unroll_number - 1) */
+      diff = expand_simple_binop (GET_MODE (diff), PLUS,
+				  diff, GEN_INT (abs_loop_inc - 1),
+				  diff, 1, OPTAB_LIB_WIDEN);
 
       /* (abs (final - initial) + abs_inc * unroll_number - 1)
 	 / (abs_inc * unroll_number)  */
Index: loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.389.2.7.2.4
retrieving revision 1.389.2.7.2.5
diff -u -r1.389.2.7.2.4 -r1.389.2.7.2.5
--- loop.c	15 Oct 2002 14:42:52 -0000	1.389.2.7.2.4
+++ loop.c	22 Nov 2002 21:20:04 -0000	1.389.2.7.2.5
@@ -3278,6 +3278,13 @@
 	  && REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
 	return 0;
 
+      /* Out-of-range regs can occur when we are called from unrolling.
+	 These have always been created by the unroller and are set in
+	 the loop, hence are never invariant. */
+
+      if (REGNO (x) >= regs->num)
+	return 0;
+
       if (regs->array[REGNO (x)].set_in_loop < 0)
 	return 2;
 
Index: doloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doloop.c,v
retrieving revision 1.16.8.2
diff -u -r1.16.8.2 doloop.c
--- doloop.c	26 Sep 2002 23:10:38 -0000	1.16.8.2
+++ doloop.c	15 Dec 2002 18:44:55 -0000
@@ -598,9 +598,13 @@
 
      If the loop has been unrolled, the full calculation is
 
-       t1 = abs_inc * unroll_number;		increment per loop
-       n = abs (final - initial) / t1;		full loops
-       n += (abs (final - initial) % t1) != 0;	partial loop
+       t1 = abs_inc * unroll_number;		        increment per loop
+       n = (abs (final - initial) + abs_inc - 1) / t1;    full loops
+       n += ((abs (final - initial) + abs_inc - 1) % t1) >= abs_inc;
+                                                          partial loop
+     which works out to be equivalent to
+
+       n = (abs (final - initial) + t1 - 1) / t1;
 
      However, in certain cases the unrolled loop will be preconditioned
      by emitting copies of the loop body with conditional branches,
@@ -682,13 +686,15 @@
       if (shift_count < 0)
 	abort ();
 
-      if (!loop_info->preconditioned)
+      if (loop_info->preconditioned)
+	diff = expand_simple_binop (GET_MODE (diff), PLUS,
+				    diff, GEN_INT (abs_inc - 1),
+				    diff, 1, OPTAB_LIB_WIDEN);
+      else
 	diff = expand_simple_binop (GET_MODE (diff), PLUS,
 				    diff, GEN_INT (abs_loop_inc - 1),
 				    diff, 1, OPTAB_LIB_WIDEN);
 
-      /* (abs (final - initial) + abs_inc * unroll_number - 1)
-	 / (abs_inc * unroll_number)  */
       diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
 				  diff, GEN_INT (shift_count),
 				  diff, 1, OPTAB_LIB_WIDEN);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]