[testcase] optimization/5076: gcc3 regression: yet another strength reduction bug

Franz Sirl Franz.Sirl-kernel@lauterbach.com
Thu Jan 3 12:57:00 GMT 2002


On Wednesday 02 January 2002 20:31, Gwenole Beauchesne wrote:
> On 11 Dec 2001 gbeauchesne@mandrakesoft.com wrote:
> > The attached test case is extracted/reduced from PR 2847 that was
> > closed earlier. gcc3 series compilers are affected, unlike gcc-2.95.X.
> > (gcc-"2.96" is affected too).
>
> Here is another testcase exhibing a strength reduction bug occurring with
> FSF gcc 3.0.3 and binutils 2.11.92.0.12-2mdk (based on RH 2.11.92.0.12-8)
> on i586-mandrake-linux-gnu. Also occurs with gcc 3.0.3 on IA-64 and with
> mainline gcc (3.1 20020102) on IA-32. This is a regression from gcc
> 2.95.X.
>
> Testcase is derived from PR optimization/5076 and PR optimization/2847.
>
> 2002-01-02  Gwenole Beauchesne  <gbeauchesne@mandrakesoft.com>
>
> 	PR optimization/5076, PR optimization/2847
> 	* gcc.c-torture/execute/loop-10.c: New test.
>
> --- gcc/testsuite/gcc.c-torture/execute/loop-10.c.strength-reduce
> Wed Jan  2 18:55:53 2002
> +++ gcc/testsuite/gcc.c-torture/execute/loop-10.c	Wed Jan  2
> 18:54:03 2002
> @@ -0,0 +1,31 @@
> +/* Reduced from PR optimization/5076, PR optimization/2847 */
> +
> +static int count = 0;
> +
> +static void
> +inc (void)
> +{
> +  count++;
> +}
> +
> +int
> +main (void)
> +{
> +  int iNbr = 1;
> +  int test = 0;
> +  while (test == 0)
> +    {
> +      inc ();
> +      if (iNbr == 0)
> +        break;
> +      else
> +        {
> +          inc ();
> +          iNbr--;
> +        }
> +      test = 1;
> +    }
> +  if (count != 2)
> +    abort ();
> +  return 0;
> +}

Actually strength reduction is innocent here, the real culprit is the overly 
simplistic loop unrolling code if the iteration count equals 1. It goes wrong 
when the insns between loop->start and loop->cont influence the exit 
condition of the loop. Since we are in bugfix mode right now (and I think a 
rewrite based on CFG is pending), I'm suggesting the attached bandaid fix for 
3.1 and gcc-3_0-branch. Correctly handling this would require to move the 
insns between loop->start and loop->cont after loop->sink, then use 
invert_jump to redirect the exit jump behind the moved insns.

Franz.

	* unroll.c (unroll_loop): Don't try to unroll loops with a
	NOTE_INSN_LOOP_CONT.
	(ujump_to_loop_cont): Delete.

-------------- next part --------------
Index: gcc/unroll.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unroll.c,v
retrieving revision 1.153
diff -u -p -r1.153 unroll.c
--- gcc/unroll.c	2001/12/30 15:58:42	1.153
+++ gcc/unroll.c	2002/01/03 20:31:02
@@ -218,7 +218,6 @@ static rtx remap_split_bivs PARAMS ((str
 static rtx find_common_reg_term PARAMS ((rtx, rtx));
 static rtx subtract_reg_term PARAMS ((rtx, rtx));
 static rtx loop_find_equiv_value PARAMS ((const struct loop *, rtx));
-static rtx ujump_to_loop_cont PARAMS ((rtx, rtx));
 
 /* Try to unroll one loop and split induction variables in the loop.
 
@@ -349,14 +348,11 @@ unroll_loop (loop, insn_count, strength_
 
   if (loop_info->n_iterations == 1)
     {
-      /* Handle the case where the loop begins with an unconditional
-	 jump to the loop condition.  Make sure to delete the jump
-	 insn, otherwise the loop body will never execute.  */
-
-      rtx ujump = ujump_to_loop_cont (loop->start, loop->cont);
-      if (ujump)
-	delete_related_insns (ujump);
+      /* Give up if there is a loop->cont (NOTE_INSN_LOOP_CONT).  */
 
+      if (loop->cont)
+	return;
+
       /* If number of iterations is exactly 1, then eliminate the compare and
 	 branch at the end of the loop since they will never be taken.
 	 Then return, since no other action is needed here.  */
@@ -4187,40 +4183,4 @@ set_dominates_use (regno, first_uid, las
 
   /* FIRST_UID is always executed if LAST_UID is executed.  */
   return 1;
-}
-
-/* This routine is called when the number of iterations for the unrolled
-   loop is one.   The goal is to identify a loop that begins with an
-   unconditional branch to the loop continuation note (or a label just after).
-   In this case, the unconditional branch that starts the loop needs to be
-   deleted so that we execute the single iteration.  */
-
-static rtx
-ujump_to_loop_cont (loop_start, loop_cont)
-     rtx loop_start;
-     rtx loop_cont;
-{
-  rtx x, label, label_ref;
-
-  /* See if loop start, or the next insn is an unconditional jump.  */
-  loop_start = next_nonnote_insn (loop_start);
-
-  x = pc_set (loop_start);
-  if (!x)
-    return NULL_RTX;
-
-  label_ref = SET_SRC (x);
-  if (!label_ref)
-    return NULL_RTX;
-
-  /* Examine insn after loop continuation note.  Return if not a label.  */
-  label = next_nonnote_insn (loop_cont);
-  if (label == 0 || GET_CODE (label) != CODE_LABEL)
-    return NULL_RTX;
-
-  /* Return the loop start if the branch label matches the code label.  */
-  if (CODE_LABEL_NUMBER (label) == CODE_LABEL_NUMBER (XEXP (label_ref, 0)))
-    return loop_start;
-  else
-    return NULL_RTX;
 }


More information about the Gcc-patches mailing list