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

Re: Re-run of loop pass


Toon Moene writes:
 > [ Rerunning loop optimisation pass ... ]
 > 
 > The interesting thing about loop unrolling in this context is, that  
 > we deliberately moved it to *after* the second loop opt phase  
 > because it suffered badly from GIVs resulting from loop unrolling  
 > being found and reduced by the second loop opt pass.  Now that GIV  
 > combining is in full force, this might not be necessary anymore:
 > 
 >       DO I = 1, N, 4
 >          X(I  ) = X(I  ) + Y(I  )
 >          X(I+1) = X(I+1) + Y(I+1)
 >          X(I+2) = X(I+2) + Y(I+2)
 >          X(I+3) = X(I+3) + Y(I+3)
 >       ENDDO
 > 
 > would previously lead to 8 registers being used for addressing,  
 > against 2 now.

I've done some experimentation with this code snippet.  With
-funroll-loops or BCT optimisation the generated code is _attrocious_
since the constant iteration count cannot be determined.  The patch at
the end seems to fix this problem (it could be generalised but for
most cases this may not be necessary).  Could someone test this on a
host machine with autoincrement addressing (such as the 68k)?

With my patch applied, I've observed the following address register
usage:

6 addr regs  -O2 -funroll-loops
4 addr regs  -O2 -funroll-loops -fno-rerun-loop-opt
2 addr regs  -O2 
2 addr regs  -O2 -fno-rerun-loop-opt

Michael.

Index: unroll.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/unroll.c,v
retrieving revision 1.32
diff -c -3 -p -r1.32 unroll.c
*** unroll.c	1998/10/14 09:02:52	1.32
--- unroll.c	1998/10/22 23:00:52
*************** loop_iterations (loop_start, loop_end)
*** 3499,3504 ****
--- 3499,3508 ----
  		  if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST
  		      && CONSTANT_P (XEXP (note, 0)))
  		    comparison_value = XEXP (note, 0);
+ 		  /* May have to check that we have the sum of a register
+ 		     and a constant.  */
+ 		  else if (GET_CODE (SET_SRC (set)) == PLUS)
+ 		    comparison_value = SET_SRC (set);
  		}
  	      break;
  	    }
*************** loop_iterations (loop_start, loop_end)
*** 3508,3513 ****
--- 3512,3581 ----
    final_value = approx_final_value (comparison_code, comparison_value,
  				    &unsigned_compare, &compare_dir);
  
+   /* initial_value = reg1, final_value = reg2 + const
+      Try to find what reg1 is equivalent to.  */
+   if (REG_P (initial_value)
+       && GET_CODE (final_value) == PLUS
+       && CONSTANT_P (XEXP (final_value, 1))
+       && XEXP (final_value, 0) != initial_value)
+     {
+       rtx insn, set;
+       
+       for (insn = PREV_INSN (loop_start); insn ; insn = PREV_INSN (insn))
+ 	{
+ 	  if (GET_CODE (insn) == CODE_LABEL)
+ 	    break;
+ 	      
+ 	  else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+ 		   && reg_set_p (initial_value, insn))
+ 	    {
+ 	      /* We found the last insn before the loop that sets the
+ 		 register.  If it sets the entire register, and has a
+ 		 REG_EQUAL note, then use, the value of the REG_EQUAL
+ 		 note.  */
+ 	      if ((set = single_set (insn))
+ 		  && (SET_DEST (set) == initial_value))
+ 		{
+ 		  rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+ 		  
+ 		  /* Only use the REG_EQUAL note if it is a constant.
+ 		     Other things, divide in particular, will cause
+ 		     problems later if we use them.  */
+ 		  if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST
+ 		      && CONSTANT_P (XEXP (note, 0)))
+ 		    initial_value = XEXP (note, 0);
+ 		  /* May have to check that we have the sum of a register
+ 		     and a constant.  */
+ 		  else if (GET_CODE (SET_SRC (set)) == PLUS)
+ 		    initial_value = SET_SRC (set);
+ 		}
+ 	      break;
+ 	    }
+ 	}
+     }
+   
+   /* initial_value = reg + const1, final_value = reg + const2 */
+   if (GET_CODE (initial_value) == PLUS
+       && GET_CODE (final_value) == PLUS
+       && CONSTANT_P (XEXP (initial_value, 1))
+       && CONSTANT_P (XEXP (final_value, 1))
+       && XEXP (final_value, 0) == XEXP (initial_value, 0))
+     {
+       final_value = GEN_INT (INTVAL (XEXP (final_value, 1)) 
+ 			     - INTVAL (XEXP (initial_value, 1)));
+       initial_value = const0_rtx;
+     }
+   
+   /* initial_value = reg, final_value = reg + const */
+   if (REG_P (initial_value)
+       && GET_CODE (final_value) == PLUS
+       && CONSTANT_P (XEXP (final_value, 1))
+       && XEXP (final_value, 0) == initial_value)
+     {
+       initial_value = const0_rtx;
+       final_value = XEXP (final_value, 1);
+     }
+   
    /* Save the calculated values describing this loop's bounds, in case
       precondition_loop_p will need them later.  These values can not be
       recalculated inside precondition_loop_p because strength reduction



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