doloop.c fix for PR 6984

Alan Modra amodra@bigpond.net.au
Tue Jun 18 06:12:00 GMT 2002


On Tue, Jun 18, 2002 at 02:38:50PM +0930, Alan Modra wrote:
> This patch fixes PR 6984, and optimizes emitted code for the
> abs_inc != 1 case.  bootstrapped and regression tested i686-linux.
> powerpc-linux test still in progress.  OK to apply assuming the ppc
> test passes?
> 
> gcc/ChangeLog
> 
> 	* doloop.c (doloop_modify_runtime <abs_inc != 1>): Simplify.
> 	(doloop_modify_runtime <do-while>): Increment initial value before
> 	comparing.  Don't emit code when NE.

Updated patch.  It's not necessary to increment the initial value before
comparing, since if initial_value + increment passes comparision_value
but initial_value doesn't pass comparison_value, we'll be calculating
a loop count of one anyway.  Apologies for the muddy thinking, caused
by (beside lack of brain) attempting to fix the corner case code
generated by PR 6984, which we now no longer generate.

gcc/ChangeLog

	* doloop.c (doloop_modify_runtime <abs_inc != 1>): Simplify.
	(doloop_modify_runtime <do-while>): Don't emit code when NE.

Index: gcc/doloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doloop.c,v
retrieving revision 1.19
diff -u -p -r1.19 doloop.c
--- gcc/doloop.c	17 Jun 2002 22:45:44 -0000	1.19
+++ gcc/doloop.c	18 Jun 2002 11:22:43 -0000
@@ -666,50 +666,22 @@ doloop_modify_runtime (loop, iterations_
   if (abs_inc * loop_info->unroll_number != 1)
     {
       int shift_count;
-      rtx extra;
-      rtx label;
-      unsigned HOST_WIDE_INT limit;
 
       shift_count = exact_log2 (abs_inc * loop_info->unroll_number);
       if (shift_count < 0)
 	abort ();
 
-      /* abs (final - initial) / (abs_inc * unroll_number)  */
-      iterations = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
-					diff, GEN_INT (shift_count),
-					NULL_RTX, 1,
-					OPTAB_LIB_WIDEN);
-
       if (abs_inc != 1)
-	{
-	  /* abs (final - initial) % (abs_inc * unroll_number)  */
-	  rtx count = GEN_INT (abs_inc * loop_info->unroll_number - 1);
-	  extra = expand_simple_binop (GET_MODE (iterations), AND,
-				       diff, count, NULL_RTX, 1,
-				       OPTAB_LIB_WIDEN);
-
-	  /* If (abs (final - initial) % (abs_inc * unroll_number)
-	       <= abs_inc * (unroll - 1)),
-	     jump past following increment instruction.  */
-	  label = gen_label_rtx ();
-	  limit = abs_inc * (loop_info->unroll_number - 1);
-	  emit_cmp_and_jump_insns (extra, GEN_INT (limit),
-				   limit == 0 ? EQ : LEU, NULL_RTX,
-				   GET_MODE (extra), 0, label);
-	  JUMP_LABEL (get_last_insn ()) = label;
-	  LABEL_NUSES (label)++;
-
-	  /* Increment the iteration count by one.  */
-	  iterations = expand_simple_binop (GET_MODE (iterations), PLUS,
-					    iterations, GEN_INT (1),
-					    iterations, 1,
-					    OPTAB_LIB_WIDEN);
-
-	  emit_label (label);
-	}
+	diff = expand_simple_binop (GET_MODE (diff), PLUS,
+				    diff, GEN_INT (abs_inc - 1),
+				    diff, 1, OPTAB_LIB_WIDEN);
+
+      /* (abs (final - initial) + abs_inc - 1) / (abs_inc * unroll_number)  */
+      diff = expand_simple_binop (GET_MODE (diff), LSHIFTRT,
+				  diff, GEN_INT (shift_count),
+				  diff, 1, OPTAB_LIB_WIDEN);
     }
-  else
-    iterations = diff;
+  iterations = diff;
 
   /* If there is a NOTE_INSN_LOOP_VTOP, we have a `for' or `while'
      style loop, with a loop exit test at the start.  Thus, we can
@@ -722,17 +694,20 @@ doloop_modify_runtime (loop, iterations_
      iteration count to one if necessary.  */
   if (! loop->vtop)
     {
-      rtx label;
-
       if (loop_dump_stream)
 	fprintf (loop_dump_stream, "Doloop: Do-while loop.\n");
 
-      /* A `do-while' loop must iterate at least once.  If the
-	 iteration count is bogus, we set the iteration count to 1.
+      /* A `do-while' loop must iterate at least once.  For code like
+	 i = initial; do { ... } while (++i < final);
+	 we will calculate a bogus iteration count if initial > final.
+	 So detect this and set the iteration count to 1.
 	 Note that if the loop has been unrolled, then the loop body
-	 is guaranteed to execute at least once.  */
-      if (loop_info->unroll_number == 1)
+	 is guaranteed to execute at least once.  Also, when the
+	 comparison is NE, our calculated count will be OK.  */
+      if (loop_info->unroll_number == 1 && comparison_code != NE)
 	{
+	  rtx label;
+
 	  /*  Emit insns to test if the loop will immediately
 	      terminate and to set the iteration count to 1 if true.  */
 	  label = gen_label_rtx();


-- 
Alan Modra
IBM OzLabs - Linux Technology Centre



More information about the Gcc-patches mailing list