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]

sh barrier_align vs. fill_eager_delay_slots


Though I can't reproduce this bug in the current gcc tree, I believe it's
still there.  gen_far_branch has the following comment:

  /* Emit a barrier so that reorg knows that any following instructions
     are not reachable via a fall-through path.
     But don't do this when not optimizing, since we wouldn't supress the
     alignment for the barrier then, and could end up with out-of-range
     pc-relative loads.  */
  if (optimize)
    emit_barrier_after (jump);

There is one case we aren't supressing the alignment, involving delayed branch
scheduling.  Currently barrier_align will catch the case where the jump before
the barrier is to the insn after the barrier (fill_simple_delay_slots) but it
doesn't handle the case where the delay slot is filled with the insn from the
jump target (fill_eager_delay_slots) and thus the jump is to two insns after
the barrier.  I'm seeing one case (in an old tree) where this is causing pcrel
out-of-range errors in the assembler, because we are emitting an align of
CACHE_LOG, but find_barrier expected the alignment to be zero.

The rtl after delayed branch scheduling is:

(insn 1458 53 1424 (sequence[
            (jump_insn 54 53 1011 (set (pc)
                    (if_then_else (ne (reg:SI 18 t)
                            (const_int 0))
                        (label_ref 1456)
                        (pc))) 160 {branch_true} (insn_list 53 (nil))
                (expr_list:REG_DEAD (reg:SI 18 t)
                    (nil)))
            (insn/s 1011 54 1424 (set (reg:SI 0 r0)
                    (const_int 108)) 121 {movsi_ie} (nil)
                (nil))
        ] ) -1 (nil)
    (nil))

(insn 1424 1458 1438 (set (pc)
        (unspec[
                (const_int 634)
            ]  4)) 162 {block_branch_redirect} (nil)
    (nil))

(insn 1438 1424 1439 (sequence[
            (jump_insn 1421 1424 1323 (set (pc)
                    (label_ref 1437)) 174 {jump} (nil)
                (nil))
            (insn/s 1323 1421 1439 (set (reg:SI 0 r0)
                    (const_int 96)) 121 {movsi_ie} (nil)
                (nil))
        ] ) -1 (nil)
    (nil))

(code_label 57 1439 59 7 "")

(insn 1011 1185 1456 (set (reg:SI 0 r0)
        (const_int 108)) 121 {movsi_ie} (nil)
    (nil))

(code_label 1456 1011 765 45 "")


Note that jump_insn 54 jumps to 1456, because it has 1011 in its delay slot.

The appended patch checks for this case.  I'm not particularly happy with it,
but the code is already rather contorted, and I don't see a cleaner way to
handle this.

2000-03-03  Clinton Popetz  <cpopetz@cygnus.com>

	* config/sh/sh.c: (barrier_align): Handle a delay slot that is
	filled with an insn from the jump target.

Index: sh.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.c,v
retrieving revision 1.50
diff -c -2 -p -r1.50 sh.c
*** sh.c	2000/02/28 21:42:55	1.50
--- sh.c	2000/03/03 14:27:26
*************** barrier_align (barrier_or_label)
*** 2712,2716 ****
  {
    rtx next = next_real_insn (barrier_or_label), pat, prev;
!   int slot, credit;
   
    if (! next)
--- 2712,2716 ----
  {
    rtx next = next_real_insn (barrier_or_label), pat, prev;
!   int slot, credit, jump_to_next;
   
    if (! next)
*************** barrier_align (barrier_or_label)
*** 2755,2758 ****
--- 2755,2765 ----
  	 branch target when there is no alignment.  */
  
+       /* There are two delay_slot cases to consider.  One is the simple case 
+ 	 where the preceding branch is to the insn beyond the barrier (simple 
+ 	 delay slot filling), and the other is where the preceding branch has 
+ 	 a delay slot that is a duplicate of the insn after the barrier 
+ 	 (fill_eager_delay_slots) and the branch is to the insn after the insn 
+ 	 after the barrier.  */
+ 
        /* PREV is presumed to be the JUMP_INSN for the barrier under
  	 investigation.  Skip to the insn before it.  */
*************** barrier_align (barrier_or_label)
*** 2763,2771 ****
  	   prev = prev_real_insn (prev))
  	{
  	  if (GET_CODE (PATTERN (prev)) == USE
  	      || GET_CODE (PATTERN (prev)) == CLOBBER)
  	    continue;
  	  if (GET_CODE (PATTERN (prev)) == SEQUENCE)
! 	    prev = XVECEXP (PATTERN (prev), 0, 1);
  	  if (slot &&
  	      get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
--- 2770,2787 ----
  	   prev = prev_real_insn (prev))
  	{
+ 	  jump_to_next = 0;
  	  if (GET_CODE (PATTERN (prev)) == USE
  	      || GET_CODE (PATTERN (prev)) == CLOBBER)
  	    continue;
  	  if (GET_CODE (PATTERN (prev)) == SEQUENCE)
! 	    {
! 	      prev = XVECEXP (PATTERN (prev), 0, 1);
! 	      if (INSN_UID (prev) == INSN_UID (next)) 
! 		{
! 	  	  /* Delay slot was filled with insn at jump target.  */
! 		  jump_to_next = 1;
!   		}
! 	    }
! 
  	  if (slot &&
  	      get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
*************** barrier_align (barrier_or_label)
*** 2776,2780 ****
  	  && GET_CODE (prev) == JUMP_INSN
  	  && JUMP_LABEL (prev)
! 	  && next_real_insn (JUMP_LABEL (prev)) == next_real_insn (barrier_or_label))
  	{
  	  rtx pat = PATTERN (prev);
--- 2792,2796 ----
  	  && GET_CODE (prev) == JUMP_INSN
  	  && JUMP_LABEL (prev)
! 	  && (jump_to_next || next_real_insn (JUMP_LABEL (prev)) == next))
  	{
  	  rtx pat = PATTERN (prev);

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