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]
Other format: [Raw text]

doloop.c fix for PR 6984


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.

Index: gcc/doloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doloop.c,v
retrieving revision 1.19
diff -c -p -r1.19 doloop.c
*** gcc/doloop.c	17 Jun 2002 22:45:44 -0000	1.19
--- gcc/doloop.c	18 Jun 2002 04:53:50 -0000
*************** doloop_modify_runtime (loop, iterations_
*** 666,715 ****
    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);
! 	}
      }
!   else
!     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
--- 666,687 ----
    if (abs_inc * loop_info->unroll_number != 1)
      {
        int shift_count;
  
        shift_count = exact_log2 (abs_inc * loop_info->unroll_number);
        if (shift_count < 0)
  	abort ();
  
        if (abs_inc != 1)
! 	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);
      }
!   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
*************** doloop_modify_runtime (loop, iterations_
*** 722,742 ****
       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.
  	 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)
  	{
  	  /*  Emit insns to test if the loop will immediately
  	      terminate and to set the iteration count to 1 if true.  */
  	  label = gen_label_rtx();
! 	  emit_cmp_and_jump_insns (copy_rtx (initial_value),
  				   copy_rtx (loop_info->comparison_value),
  				   comparison_code, NULL_RTX, mode, 0,
  				   label);
--- 694,721 ----
       iteration count to one if necessary.  */
    if (! loop->vtop)
      {
        if (loop_dump_stream)
  	fprintf (loop_dump_stream, "Doloop: Do-while loop.\n");
  
!       /* 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.  Also, when the
! 	 comparison is NE, our calculated count will be OK.  */
!       if (loop_info->unroll_number == 1 && comparison_code != NE)
  	{
+ 	  rtx label;
+ 	  rtx after_one;
+ 
  	  /*  Emit insns to test if the loop will immediately
  	      terminate and to set the iteration count to 1 if true.  */
  	  label = gen_label_rtx();
! 	  after_one = expand_simple_binop (mode, PLUS,
! 					   initial_value, increment, NULL_RTX,
! 					   unsigned_p, OPTAB_LIB_WIDEN);
! 	  emit_cmp_and_jump_insns (after_one,
  				   copy_rtx (loop_info->comparison_value),
  				   comparison_code, NULL_RTX, mode, 0,
  				   label);

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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