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]

patch applied to sh port: fix alignments / insn length problem


This patch makes the sh port honour the align_jumps / align_loops
settings, and when relaxing, it makes the align_function setting
large enough so that no alignment inside a function emitted by gcc
is larger than the alignment of the function as a whole.

I've also fixed an insn size bug where the compiler found a scratch
register for a far jump and thus knew that the jump would take only
6 bytes + delay slot, but lost track of the scratch register as
INSN_SCOPE notes were emitted.
	 
-- 
--------------------------
SuperH (UK) Ltd.
2410 Aztec West / Almondsbury / BRISTOL / BS32 4QX
T:+44 1454 465658
Mon Mar  3 19:47:26 2003  J"orn Rennecke <joern dot rennecke at superh dot com>

	* sh.h (OVERRIDE_OPTIONS): Set default values for align_loops
	and align_jumps if not set.
	Force align_jumps to be at least 2.
	When relaxing, force align_functions to be at least the maximum of
	align_loops, align_jumps and 4.
	* sh.c (find_barrier, barrier_align): Honour align_jumps_log.
	(sh_loop_align): Honour align_loops_log.

	* sh.md (length attribute): Use prev_nonnote_insn instead of PREV_INSN
	to check for indirect_jump_scratch.
	(indirect_jump_scratch): Add second set.
	* sh.c (output_far_jump): Use prev_nonnote_insn instead of PREV_INSN
	when looking for indirect_jump_scratch.
	Extract scratch register taking new structure of indirect_jump_scratch
	into account.
	(gen_block_redirect): Set INSN_SCOPE for indirect_jump_scratch.

Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.200
diff -p -r1.200 sh.c
*** config/sh/sh.c	24 Feb 2003 02:44:01 -0000	1.200
--- config/sh/sh.c	3 Mar 2003 19:25:05 -0000
*************** output_far_jump (insn, op)
*** 1048,1053 ****
--- 1048,1054 ----
    const char *jump;
    int far;
    int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
+   rtx prev;
  
    this.lab = gen_label_rtx ();
  
*************** output_far_jump (insn, op)
*** 1072,1081 ****
  	jump = "mov.l	%O0,%1; jmp	@%1";
      }
    /* If we have a scratch register available, use it.  */
!   if (GET_CODE (PREV_INSN (insn)) == INSN
!       && INSN_CODE (PREV_INSN (insn)) == CODE_FOR_indirect_jump_scratch)
      {
!       this.reg = SET_DEST (PATTERN (PREV_INSN (insn)));
        if (REGNO (this.reg) == R0_REG && flag_pic && ! TARGET_SH2)
  	jump = "mov.l	r1,@-r15; mova	%O0,r0; mov.l	@r0,r1; add	r1,r0; mov.l	@r15+,r1; jmp	@%1";
        output_asm_insn (jump, &this.lab);
--- 1073,1082 ----
  	jump = "mov.l	%O0,%1; jmp	@%1";
      }
    /* If we have a scratch register available, use it.  */
!   if (GET_CODE ((prev = prev_nonnote_insn (insn))) == INSN
!       && INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)
      {
!       this.reg = SET_DEST (XVECEXP (PATTERN (prev), 0, 0));
        if (REGNO (this.reg) == R0_REG && flag_pic && ! TARGET_SH2)
  	jump = "mov.l	r1,@-r15; mova	%O0,r0; mov.l	@r0,r1; add	r1,r0; mov.l	@r15+,r1; jmp	@%1";
        output_asm_insn (jump, &this.lab);
*************** find_barrier (num_mova, mova, from)
*** 3016,3022 ****
  	{
  	  if (num_mova)
  	    num_mova--;
! 	  if (barrier_align (next_real_insn (from)) == CACHE_LOG)
  	    {
  	      /* We have just passed the barrier in front of the
  		 ADDR_DIFF_VEC, which is stored in found_barrier.  Since
--- 3017,3023 ----
  	{
  	  if (num_mova)
  	    num_mova--;
! 	  if (barrier_align (next_real_insn (from)) == align_jumps_log)
  	    {
  	      /* We have just passed the barrier in front of the
  		 ADDR_DIFF_VEC, which is stored in found_barrier.  Since
*************** gen_block_redirect (jump, addr, need_blo
*** 3454,3459 ****
--- 3455,3467 ----
        rtx insn = emit_insn_before (gen_indirect_jump_scratch
  				   (reg, GEN_INT (INSN_UID (JUMP_LABEL (jump))))
  				   , jump);
+       /* ??? We would like this to have the scope of the jump, but that
+ 	 scope will change when a delay slot insn of an inner scope is added.
+ 	 Hence, after delay slot scheduling, we'll have to expect
+ 	 NOTE_INSN_BLOCK_END notes between the indirect_jump_scratch and
+ 	 the jump.  */
+ 	 
+       INSN_SCOPE (insn) = INSN_SCOPE (jump);
        INSN_CODE (insn) = CODE_FOR_indirect_jump_scratch;
        return insn;
      }
*************** barrier_align (barrier_or_label)
*** 3596,3609 ****
        return ((TARGET_SMALLCODE
  	       || ((unsigned) XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
  		   <= (unsigned)1 << (CACHE_LOG - 2)))
! 	      ? 1 << TARGET_SHMEDIA : CACHE_LOG);
      }
  
    if (TARGET_SMALLCODE)
      return 0;
  
    if (! TARGET_SH2 || ! optimize)
!     return CACHE_LOG;
  
    /* When fixing up pcloads, a constant table might be inserted just before
       the basic block that ends with the barrier.  Thus, we can't trust the
--- 3604,3617 ----
        return ((TARGET_SMALLCODE
  	       || ((unsigned) XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
  		   <= (unsigned)1 << (CACHE_LOG - 2)))
! 	      ? 1 << TARGET_SHMEDIA : align_jumps_log);
      }
  
    if (TARGET_SMALLCODE)
      return 0;
  
    if (! TARGET_SH2 || ! optimize)
!     return align_jumps_log;
  
    /* When fixing up pcloads, a constant table might be inserted just before
       the basic block that ends with the barrier.  Thus, we can't trust the
*************** barrier_align (barrier_or_label)
*** 3679,3685 ****
  	}
      }
    
!   return CACHE_LOG;
  }
  
  /* If we are inside a phony loop, almost any kind of label can turn up as the
--- 3687,3693 ----
  	}
      }
    
!   return align_jumps_log;
  }
  
  /* If we are inside a phony loop, almost any kind of label can turn up as the
*************** sh_loop_align (label)
*** 3704,3713 ****
        || recog_memoized (next) == CODE_FOR_consttable_2)
      return 0;
  
!   if (TARGET_SH5)
!     return 3;
! 
!   return 2;
  }
  
  /* Exported to toplev.c.
--- 3712,3718 ----
        || recog_memoized (next) == CODE_FOR_consttable_2)
      return 0;
  
!   return align_loops_log;
  }
  
  /* Exported to toplev.c.
*************** split_branches (first)
*** 4417,4425 ****
  
     If relaxing, output the label and pseudo-ops used to link together
     calls and the instruction which set the registers.  */
- 
- /* ??? This is unnecessary, and probably should be deleted.  This makes
-    the insn_addresses declaration above unnecessary.  */
  
  /* ??? The addresses printed by this routine for insns are nonsense for
     insns which are inside of a sequence where none of the inner insns have
--- 4422,4427 ----
Index: config/sh/sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.191
diff -p -r1.191 sh.h
*** config/sh/sh.h	24 Feb 2003 02:44:01 -0000	1.191
--- config/sh/sh.h	3 Mar 2003 19:25:05 -0000
*************** do {									\
*** 489,494 ****
--- 489,501 ----
        flag_schedule_insns = 0;						\
      }									\
  									\
+   if (align_loops == 0)							\
+     align_loops =  1 << (TARGET_SH5 ? 3 : 2);				\
+   if (align_jumps == 0)							\
+     align_jumps = 1 << CACHE_LOG;					\
+   else if (align_jumps <= 1)						\
+     align_jumps = 2;							\
+ 									\
    /* Allocation boundary (in *bytes*) for the code of a function.	\
       SH1: 32 bit alignment is faster, because instructions are always	\
       fetched as a pair from a longword boundary.			\
*************** do {									\
*** 496,501 ****
--- 503,522 ----
    if (align_functions == 0)						\
      align_functions							\
        = TARGET_SMALLCODE ? FUNCTION_BOUNDARY/8 : (1 << CACHE_LOG);	\
+   /* The linker relaxation code breaks when a function contains		\
+      alignments that are larger than that at the start of a		\
+      compilation unit.  */						\
+   if (TARGET_RELAX)							\
+     {									\
+       int min_align							\
+ 	= align_loops > align_jumps ? align_loops : align_jumps;	\
+ 									\
+       /* Also take possible .long constants / mova tables int account.	*/\
+       if (min_align < 4)						\
+ 	min_align = 4;							\
+       if (align_functions < min_align)					\
+ 	align_functions = min_align;					\
+     }									\
  } while (0)
  
  /* Target machine storage layout.  */
Index: config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.140
diff -p -r1.140 sh.md
*** config/sh/sh.md	24 Feb 2003 02:44:02 -0000	1.140
--- config/sh/sh.md	3 Mar 2003 19:25:05 -0000
***************
*** 391,399 ****
  	 (eq_attr "type" "jump")
  	 (cond [(eq_attr "med_branch_p" "yes")
  		(const_int 2)
! 		(and (eq (symbol_ref "GET_CODE (PREV_INSN (insn))")
  			 (symbol_ref "INSN"))
! 		     (eq (symbol_ref "INSN_CODE (PREV_INSN (insn))")
  			 (symbol_ref "code_for_indirect_jump_scratch")))
  		(if_then_else (eq_attr "braf_branch_p" "yes")
  			      (const_int 6)
--- 391,399 ----
  	 (eq_attr "type" "jump")
  	 (cond [(eq_attr "med_branch_p" "yes")
  		(const_int 2)
! 		(and (eq (symbol_ref "GET_CODE (prev_nonnote_insn (insn))")
  			 (symbol_ref "INSN"))
! 		     (eq (symbol_ref "INSN_CODE (prev_nonnote_insn (insn))")
  			 (symbol_ref "code_for_indirect_jump_scratch")))
  		(if_then_else (eq_attr "braf_branch_p" "yes")
  			      (const_int 6)
***************
*** 5035,5043 ****
  
  ;; This one has the additional purpose to record a possible scratch register
  ;; for the following branch.
  (define_insn "indirect_jump_scratch"
    [(set (match_operand:SI 0 "register_operand" "=r")
! 	(unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR))]
    "TARGET_SH1"
    ""
    [(set_attr "length" "0")])
--- 5035,5048 ----
  
  ;; This one has the additional purpose to record a possible scratch register
  ;; for the following branch.
+ ;; ??? Unfortunately, just setting the scratch register is not good enough,
+ ;; because the insn then might be deemed dead and deleted.  And we can't
+ ;; make the use in the jump insn explicit because that would disable
+ ;; delay slot scheduling from the target.
  (define_insn "indirect_jump_scratch"
    [(set (match_operand:SI 0 "register_operand" "=r")
! 	(unspec:SI [(match_operand 1 "const_int_operand" "")] UNSPEC_BBR)) 
!    (set (pc) (unspec [(const_int 0)] UNSPEC_BBR))]
    "TARGET_SH1"
    ""
    [(set_attr "length" "0")])
***************
*** 5474,5479 ****
--- 5479,5497 ----
  }"
    [(set_attr "type" "jump")
     (set_attr "needs_delay_slot" "yes")])
+ 
+ ;; ??? It would be much saner to explicitly use the scratch register
+ ;; in the jump insn, and have indirect_jump_scratch only set it,
+ ;; but fill_simple_delay_slots would refuse to do delay slot filling
+ ;; from the target then, as it uses simplejump_p.
+ ;;(define_insn "jump_compact_far"
+ ;;  [(set (pc)
+ ;;	(label_ref (match_operand 0 "" "")))
+ ;;   (use (match_operand 1 "register_operand" "r")]
+ ;;  "TARGET_SH1"
+ ;;  "* return output_far_jump(insn, operands[0], operands[1]);"
+ ;;  [(set_attr "type" "jump")
+ ;;   (set_attr "needs_delay_slot" "yes")])
  
  (define_insn "jump_media"
    [(set (pc)

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