This is the mail archive of the gcc-patches@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]

loop unrolling bugfix



Compile on an x86 with -O2 -funroll-loops.  The compiler will abort:

static int
regex_compile ()
{
  int  c, c1;
  char str[6  + 1];
  c1 = 0;
  for (;;)
    {
      do { } while (0) ;
      if (c1 == 6 )
        break;
      str[c1++] = c;
    }
}  


The problem is the unrolling code wants to unroll the outer loop, but
the outer loop starts with a jump to its exit code.  unroll.c thinks
this can never happen and aborts.

It happens in this case because duplicate_loop_exit_test sees loop
notes for the inner loop in exit code for the outer loop.  So the
exit code for the outer loop is not duplicated.

However we can still determine the number of iterations for the outer
loop, so unroll.c thinks it can/should unroll the outer loop.

Here's a patch that makes unroll ignore this situation instead of
aborting.

	* unroll.c (unroll_loop): Do not abort for an UNROLL_MODULO
	or UNROLL_COMPLETELY loop that starts with a jump to its
	exit code.

Index: unroll.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/./gcc/unroll.c,v
retrieving revision 1.29
diff -c -3 -p -r1.29 unroll.c
*** unroll.c	1998/06/29 17:36:02	1.29
--- unroll.c	1998/07/29 06:20:19
*************** unroll_loop (loop_end, insn_count, loop_
*** 431,445 ****
  
    if (unroll_type == UNROLL_COMPLETELY || unroll_type == UNROLL_MODULO)
      {
!       /* Loops of these types should never start with a jump down to
! 	 the exit condition test.  For now, check for this case just to
! 	 be sure.  UNROLL_NAIVE loops can be of this form, this case is
! 	 handled below.  */
        insn = loop_start;
        while (GET_CODE (insn) != CODE_LABEL && GET_CODE (insn) != JUMP_INSN)
  	insn = NEXT_INSN (insn);
        if (GET_CODE (insn) == JUMP_INSN)
! 	abort ();
      }
  
    if (unroll_type == UNROLL_COMPLETELY)
--- 431,464 ----
  
    if (unroll_type == UNROLL_COMPLETELY || unroll_type == UNROLL_MODULO)
      {
!       /* Loops of these types can start with jump down to the exit condition
! 	 in rare circumstances.
! 
! 	 Consider a pair of nested loops where the inner loop is part
! 	 of the exit code for the outer loop.
! 
! 	 In this case jump.c will not duplicate the exit test for the outer
! 	 loop, so it will start with a jump to the exit code.
! 
! 	 Then consider if the inner loop turns out to iterate once and
! 	 only once.  We will end up deleting the jumps associated with
! 	 the inner loop.  However, the loop notes are not removed from
! 	 the instruction stream.
! 
! 	 And finally assume that we can compute the number of iterations
! 	 for the outer loop.
! 
! 	 In this case unroll may want to unroll the outer loop even though
! 	 it starts with a jump to the outer loop's exit code.
! 
! 	 We could try to optimize this case, but it hardly seems worth it.
! 	 Just return without unrolling the loop in such cases.  */
! 
        insn = loop_start;
        while (GET_CODE (insn) != CODE_LABEL && GET_CODE (insn) != JUMP_INSN)
  	insn = NEXT_INSN (insn);
        if (GET_CODE (insn) == JUMP_INSN)
! 	return;
      }
  
    if (unroll_type == UNROLL_COMPLETELY)



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