more ia32 bugs (unrolling)

Richard Henderson rth@cygnus.com
Sun Jun 27 01:11:00 GMT 1999


On Tue, Jun 22, 1999 at 09:53:56PM -0600, Jeffrey A Law wrote:
>   > JUMP_LABEL comes up 0.  :-( And we die for it.  In the old compiler,
>   > no such code.  I checked the source out, and this is new code:
>
> Err, I'd like to see last_loop_insn for this case.  Something sounds pretty
> bogus since I see nothing in that code which should lead to a jump with a
> null JUMP_LABEL.

Any jump created during loop won't have its JUMP_LABEL set unless
the immediately surrounding code takes care of that.  This is 
showing up with the check_decr_loop code Bob wrote.

I don't know why we didn't run into this before, as the bct code
makes the same mistake several places.  Nor do I know why this didn't
show up in the Cygnus tree.

Anyway, here's what I'm doing to correct the problem.


r~



	* loop.c (loop_emit_jump_insn_before): New function.
	(loop_emit_jump_insn_after): Likewise.
	(check_dbra_loop): Use it.
	(instrument_loop_bct): Likewise.
	(fixup_decr_loop_info): Likewise.
	(check_decr_loop): Likewise.  Delete unused variables.

Index: loop.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/loop.c,v
retrieving revision 1.165.2.1
diff -c -p -d -r1.165.2.1 loop.c
*** loop.c	1999/06/21 20:52:42	1.165.2.1
--- loop.c	1999/06/27 08:01:08
*************** static int insert_loop_mem PROTO((rtx *,
*** 358,363 ****
--- 358,366 ----
  static int replace_loop_mem PROTO((rtx *, void *));
  static int replace_label PROTO((rtx *, void *));
  
+ static rtx loop_emit_jump_insn_before PROTO((rtx, rtx, rtx));
+ static rtx loop_emit_jump_insn_after PROTO((rtx, rtx, rtx));
+ 
  typedef struct rtx_and_int {
    rtx r;
    int i;
*************** check_dbra_loop (loop_end, insn_count, l
*** 8389,8403 ****
  				       XEXP (jump_label, 0));
  	      tem = gen_sequence ();
  	      end_sequence ();
! 	      emit_jump_insn_before (tem, loop_end);
! 
! 	      for (tem = PREV_INSN (loop_end);
! 		   tem && GET_CODE (tem) != JUMP_INSN;
! 		   tem = PREV_INSN (tem))
! 		;
! 
! 	      if (tem)
! 		JUMP_LABEL (tem) = XEXP (jump_label, 0);
  
  	      if (nonneg)
  		{
--- 8392,8398 ----
  				       XEXP (jump_label, 0));
  	      tem = gen_sequence ();
  	      end_sequence ();
! 	      loop_emit_jump_insn_before (tem, loop_end, XEXP (jump_label, 0));
  
  	      if (nonneg)
  		{
*************** fixup_decr_loop_info (loop_info, bl, loo
*** 8671,8677 ****
       deleted as a dead reg). */
    delete_insn (inner_set);
  
!   emit_jump_insn_before (p, loop_end);
  
    delete_insn (outer_decr_insn);
  
--- 8666,8672 ----
       deleted as a dead reg). */
    delete_insn (inner_set);
  
!   loop_emit_jump_insn_before (p, loop_end, XEXP (jump_label, 0));
  
    delete_insn (outer_decr_insn);
  
*************** fixup_decr_loop_info (loop_info, bl, loo
*** 8690,8696 ****
  				   JUMP_LABEL (outer_jump_insn));
  	  p = gen_sequence ();
  	  end_sequence ();
! 	  emit_jump_insn_after (p, outer_jump_insn);
  	  delete_insn (outer_compare_insn);
  	  if (outer_compare_insn != outer_jump_insn)
  	    delete_insn (outer_jump_insn);
--- 8685,8692 ----
  				   JUMP_LABEL (outer_jump_insn));
  	  p = gen_sequence ();
  	  end_sequence ();
! 	  loop_emit_jump_insn_after (p, outer_jump_insn,
! 				     JUMP_LABEL (outer_jump_insn));
  	  delete_insn (outer_compare_insn);
  	  if (outer_compare_insn != outer_jump_insn)
  	    delete_insn (outer_jump_insn);
*************** check_decr_loop (loop_end, insn_count, l
*** 8718,8724 ****
    int compare_with_prev = 0;
    rtx inner_set;
    rtx initial_jump_label = NULL_RTX;
-   rtx original_initial_value;
  
    /* If there is more than one exit from the loop, we can't optimize
       it. */
--- 8714,8719 ----
*************** check_decr_loop (loop_end, insn_count, l
*** 8763,8769 ****
  
    if (! bl)
      {
-       rtx p;
        /* The loop test may be of the form
  	 tmp = a;
  	 a--;
--- 8758,8763 ----
*************** check_decr_loop (loop_end, insn_count, l
*** 8936,8942 ****
  			   XEXP (jump_label, 0));   
    insn = gen_sequence ();
    end_sequence ();
!   emit_jump_insn_before (insn, loop_end);
  
    if (bl->initial_test_jump)
      {
--- 8930,8936 ----
  			   XEXP (jump_label, 0));   
    insn = gen_sequence ();
    end_sequence ();
!   loop_emit_jump_insn_before (insn, loop_end, XEXP (jump_label, 0));
  
    if (bl->initial_test_jump)
      {
*************** check_decr_loop (loop_end, insn_count, l
*** 8953,8959 ****
  			       initial_jump_label);
        insn = gen_sequence ();
        end_sequence ();
!       insn = emit_jump_insn_before (insn, initial_compare);
        delete_insn (bl->initial_test_jump);
        if (bl->initial_test_jump != initial_compare)
  	delete_insn (initial_compare);
--- 8947,8954 ----
  			       initial_jump_label);
        insn = gen_sequence ();
        end_sequence ();
!       insn = loop_emit_jump_insn_before (insn, initial_compare,
! 					 initial_jump_label);
        delete_insn (bl->initial_test_jump);
        if (bl->initial_test_jump != initial_compare)
  	delete_insn (initial_compare);
*************** instrument_loop_bct (loop_start, loop_en
*** 10119,10127 ****
        /* Insert new comparison on the count register instead of the
  	 old one, generating the needed BCT pattern (that will be
  	 later recognized by assembly generation phase).  */
!       emit_jump_insn_before (gen_decrement_and_branch_on_count (counter_reg,
! 								start_label),
! 			     loop_end);
        LABEL_NUSES (start_label)++;
      }
  
--- 10114,10122 ----
        /* Insert new comparison on the count register instead of the
  	 old one, generating the needed BCT pattern (that will be
  	 later recognized by assembly generation phase).  */
!       loop_emit_jump_insn_before
! 	(gen_decrement_and_branch_on_count (counter_reg, start_label),
! 	 loop_end, start_label);
        LABEL_NUSES (start_label)++;
      }
  
*************** replace_label (x, data)
*** 10559,10561 ****
--- 10554,10593 ----
    return 0;
  }
  
+ /* Like emit_jump_insn_before, except initialize the jump insn's
+    JUMP_LABEL to LABEL.  */
+ 
+ static rtx
+ loop_emit_jump_insn_before (insn, before, label)
+      rtx insn, before, label;
+ {
+   rtx p, ret;
+ 
+   ret = emit_jump_insn_before (insn, before);
+   for (p = ret; p ; p = NEXT_INSN (p))
+     if (GET_CODE (p) == JUMP_INSN)
+       {
+ 	JUMP_LABEL (p) = label;
+ 	return ret;
+       }
+   abort ();
+ }
+ 
+ /* Like emit_jump_insn_after, except initialize the jump insn's
+    JUMP_LABEL to LABEL.  */
+ 
+ static rtx
+ loop_emit_jump_insn_after (insn, after, label)
+      rtx insn, after, label;
+ {
+   rtx p, ret;
+ 
+   ret = emit_jump_insn_after (insn, after);
+   for (p = NEXT_INSN (after); p ; p = NEXT_INSN (p))
+     if (GET_CODE (p) == JUMP_INSN)
+       {
+ 	JUMP_LABEL (p) = label;
+ 	return ret;
+       }
+   abort ();
+ }


More information about the Gcc-patches mailing list