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]

[patch] to correct bad unrolling


The attached patch corrects a problem with the unroller when 
the number of loop iterations is one.  Presented with a loop
of this form:

    loop begin
    goto label1
label2:
       ...
    loop cont
label1:
    if (cond) goto label2
    loop end
    
the unroller would delete the loop begin note, the loop cont note
and the last insn in the loop, in this case the if stmt.  This
left us with an unconditional branch around the loop causing no
iterations to be performed.

This patch tries to detect the above situation and delete the
initial branch.  This was bootstrapped and tested on i686-pc-linux-gnu.
Okay to install?

Catherine

2000-09-01  Catherine Moore  <clm@redhat.com>

        * unroll.c (unroll_loop): Check for unconditional jumps
        to loop continuation.  Delete if n_iterations is 1.
        (ujump_to_loop_cont): New routine.

Index: unroll.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/unroll.c,v
retrieving revision 1.103
diff -p -r1.103 unroll.c
*** unroll.c	2000/08/21 19:58:34	1.103
--- unroll.c	2000/09/01 15:16:53
*************** static rtx remap_split_bivs PARAMS ((rtx
*** 216,221 ****
--- 216,222 ----
  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.
  
*************** unroll_loop (loop, insn_count, end_inser
*** 348,353 ****
--- 349,362 ----
  
    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_insn (ujump);
+ 	
        /* 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.  */
*************** set_dominates_use (regno, first_uid, las
*** 4152,4154 ****
--- 4161,4201 ----
    /* 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;
+ 
+ }
+ 
+ 

gcc/testsuite/ChangeLog:

2000-09-01  Catherine Moore  <clm@redhat.com>

	* gcc.c-torture/execute/unroll-1.c: New test.

/* gcc.c-torture/execute/unroll-1.c */
inline int
f (int x)
{
  return (x + 1);
}
 
int
main (void)
{
  int a = 0 ;
 
  while ( (f(f(f(f(f(f(f(f(f(f(1))))))))))) + a < 12 )
    {
      a++;
      exit (0);
    }
  if (a != 1)
    abort();
}


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