[CVS 980420] Still strength-reduce bug on HP-UX!

Jim Wilson wilson@cygnus.com
Tue Apr 21 22:12:00 GMT 1998


The problem here is that check_dbra_loop is reversing a loop when it is
not safe to do so.  check_dbra_loop is confused because it assumes that
there are always two instructions (a compare and a branch) at the end of the
loop, but the HPPA only puts one compare-and-branch insn at the end of the
loop.

I know that Jeff Law has run into this problem in a different context, and I
know that Joern Rennecke has been working on a patch to improve this
function which fixes some problems, but doesn't seem to fix this one.

I stole an idea from Joern's patch, and came up with this quick solution to
the problem, which seems to make things better without introducing any new
problems.  I haven't tried testing this patch on anything other than the
provided example though.

Tue Apr 21 21:12:48 1998  Jim Wilson  <wilson@cygnus.com>

	* loop.c (check_dbra_loop): New locals jump, first_compare, and
	compare_and_branch.  Call get_condition to set first_compare.
	Set compare_and_branch to number of compare/branch instructions.
	Replace PREV_INSN (PREV_INSN (loop_end)) with first_compare.
	Replace '2' with compare_and_branch.

Index: loop.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.c,v
retrieving revision 1.42
diff -p -r1.42 loop.c
*** loop.c	1998/04/16 23:56:12	1.42
--- loop.c	1998/04/22 04:11:52
*************** check_dbra_loop (loop_end, insn_count, l
*** 6093,6106 ****
    rtx comparison;
    rtx before_comparison;
    rtx p;
  
    /* If last insn is a conditional branch, and the insn before tests a
       register value, try to optimize it.  Otherwise, we can't do anything.  */
  
!   comparison = get_condition_for_loop (PREV_INSN (loop_end));
    if (comparison == 0)
      return 0;
  
    /* Check all of the bivs to see if the compare uses one of them.
       Skip biv's set more than once because we can't guarantee that
       it will be zero on the last iteration.  Also skip if the biv is
--- 6093,6118 ----
    rtx comparison;
    rtx before_comparison;
    rtx p;
+   rtx jump;
+   rtx first_compare;
+   int compare_and_branch;
  
    /* If last insn is a conditional branch, and the insn before tests a
       register value, try to optimize it.  Otherwise, we can't do anything.  */
  
!   jump = PREV_INSN (loop_end);
!   comparison = get_condition_for_loop (jump);
    if (comparison == 0)
      return 0;
  
+   /* Try to compute whether the compare/branch at the loop end is one or
+      two instructions.  */
+   get_condition (jump, &first_compare);
+   if (first_compare == jump)
+     compare_and_branch = 1;
+   else
+     compare_and_branch = 2;
+ 
    /* Check all of the bivs to see if the compare uses one of them.
       Skip biv's set more than once because we can't guarantee that
       it will be zero on the last iteration.  Also skip if the biv is
*************** check_dbra_loop (loop_end, insn_count, l
*** 6111,6117 ****
        if (bl->biv_count == 1
  	  && bl->biv->dest_reg == XEXP (comparison, 0)
  	  && ! reg_used_between_p (regno_reg_rtx[bl->regno], bl->biv->insn,
! 				   PREV_INSN (PREV_INSN (loop_end))))
  	break;
      }
  
--- 6123,6129 ----
        if (bl->biv_count == 1
  	  && bl->biv->dest_reg == XEXP (comparison, 0)
  	  && ! reg_used_between_p (regno_reg_rtx[bl->regno], bl->biv->insn,
! 				   first_compare))
  	break;
      }
  
*************** check_dbra_loop (loop_end, insn_count, l
*** 6252,6258 ****
  	  && reversible_mem_store
  	  && (no_use_except_counting
  	      || ((bl->giv_count + bl->biv_count + num_mem_sets
! 		   + num_movables + 2 == insn_count)
  		  && (bl == loop_iv_list && bl->next == 0))))
  	{
  	  rtx tem;
--- 6264,6270 ----
  	  && reversible_mem_store
  	  && (no_use_except_counting
  	      || ((bl->giv_count + bl->biv_count + num_mem_sets
! 		   + num_movables + compare_and_branch == insn_count)
  		  && (bl == loop_iv_list && bl->next == 0))))
  	{
  	  rtx tem;
*************** check_dbra_loop (loop_end, insn_count, l
*** 6344,6359 ****
  
  	      /* Emit an insn after the end of the loop to set the biv's
  		 proper exit value if it is used anywhere outside the loop.  */
! 	      if ((REGNO_LAST_UID (bl->regno)
! 		   != INSN_UID (PREV_INSN (PREV_INSN (loop_end))))
  		  || ! bl->init_insn
  		  || REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn))
  		emit_insn_after (gen_move_insn (reg, final_value),
  				 loop_end);
  
  	      /* Delete compare/branch at end of loop.  */
- 	      delete_insn (PREV_INSN (loop_end));
  	      delete_insn (PREV_INSN (loop_end));
  
  	      /* Add new compare/branch insn at end of loop.  */
  	      start_sequence ();
--- 6356,6371 ----
  
  	      /* Emit an insn after the end of the loop to set the biv's
  		 proper exit value if it is used anywhere outside the loop.  */
! 	      if ((REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
  		  || ! bl->init_insn
  		  || REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn))
  		emit_insn_after (gen_move_insn (reg, final_value),
  				 loop_end);
  
  	      /* Delete compare/branch at end of loop.  */
  	      delete_insn (PREV_INSN (loop_end));
+ 	      if (compare_and_branch == 2)
+ 		delete_insn (first_compare);
  
  	      /* Add new compare/branch insn at end of loop.  */
  	      start_sequence ();




More information about the Gcc-bugs mailing list