This is the mail archive of the gcc-prs@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]

Re: target/4516: [SH] sh-unknown-linux-gnu: big jump table


The following reply was made to PR target/4516; it has been noted by GNATS.

From: NIIBE Yutaka <gniibe@m17n.org>
To: rodrigc@gcc.gnu.org, gcc-bugs@gcc.gnu.org, gcc-prs@gcc.gnu.org,
   nobody@gcc.gnu.org, gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: target/4516: [SH] sh-unknown-linux-gnu: big jump table
Date: Mon, 25 Feb 2002 15:39:06 +0900 (JST)

 rodrigc@gcc.gnu.org wrote:
  > Old Synopsis: sh-unknown-linux-gnu: big jump table
  > New Synopsis: [SH] sh-unknown-linux-gnu: big jump table
  > 
  > State-Changed-From-To: open->feedback
  > State-Changed-By: rodrigc
  > State-Changed-When: Sun Feb 24 12:08:31 2002
  > State-Changed-Why:
  >     Is this solved in the current compiler?
 
 I don't think it's fixed.
 
 The issue here is that alignement calculation could be wrong.
 
 I've been using following patch (re-diffed and re-wrote ChangeLog entries),
 with no problem to bootstrap.
 
 2002-02-25  NIIBE Yutaka  <gniibe@m17n.org>
 
 	* final.c (shorten_branches): Update insn_current_address
 	in the for loop.
 	Set insn_current_address to be aligned.
 
 	* doc/invoke.texi (Option Summary: SH Options): Remove -mbigtable.
 
 	* config/sh/sh-protos.h (shl_casesi_worker_length): New function.
 
 	* config/sh/sh.c (shl_casesi_worker_length): New function.
 
 	* config/sh/sh.h (BIGTABLE_BIT, TARGET_BIGTABLE): Removed.
 	(optimized_size): Declared.
 	(TARGET_SWITCHES): Remove -mbigtable option.
 	(CASE_VECTOR_MODE): Always SImode.  Starting from QImode (or
 	HImode) may result assembler error of "pcrel too far" (e.g.
 	compiling f/symbol.c).  It's because barrier_align depends
 	on the mode.
 	(CASE_VECTOR_SHORTEN_MODE): When it's 32768..65536 and -Os,
 	Use HImode with offset_unsigned =1.
 	(ASM_OUTPUT_ADDR_VEC_ELT): Always emit as .long.
 
 	* config/sh/sh.md (*casesi_worker): Handle the case of
 	offset_unsigned is set when HImode.
 	Set length attribute with shl_casesi_worker_length.
 
 --- gcc-HEAD/gcc/final.c	Mon Feb 25 11:26:13 2002
 +++ gcc/gcc/final.c	Mon Feb 25 11:35:43 2002
 @@ -1115,7 +1115,7 @@
    /* Compute initial lengths, addresses, and varying flags for each insn.  */
    for (insn_current_address = FIRST_INSN_ADDRESS, insn = first;
         insn != 0;
 -       insn_current_address += insn_lengths[uid], insn = NEXT_INSN (insn))
 +       insn = NEXT_INSN (insn))
      {
        uid = INSN_UID (insn);
  
 @@ -1129,6 +1129,7 @@
  	      int align = 1 << log;
  	      int new_address = (insn_current_address + align - 1) & -align;
  	      insn_lengths[uid] = new_address - insn_current_address;
 +	      insn_current_address = new_address;
  	    }
  	}
  
 @@ -1208,6 +1209,8 @@
        if (insn_lengths[uid] < 0)
  	fatal_insn ("negative insn length", insn);
  #endif
 +
 +      insn_current_address += insn_lengths[uid];
      }
  
    /* Now loop over all the insns finding varying length insns.  For each,
 --- gcc-HEAD/gcc/doc/invoke.texi	Mon Feb 25 11:27:29 2002
 +++ gcc/gcc/doc/invoke.texi	Mon Feb 25 11:38:00 2002
 @@ -544,7 +544,7 @@
  -m5-32media -m5-32media-nofpu @gol
  -m5-compact -m5-compact-nofpu @gol
  -mb  -ml  -mdalign  -mrelax @gol
 --mbigtable  -mfmovd  -mhitachi  -mnomacsave @gol
 +-mfmovd  -mhitachi  -mnomacsave @gol
  -mieee  -misize  -mpadstruct  -mspace @gol
  -mprefergot  -musermode}
  
 @@ -8545,11 +8545,6 @@
  Shorten some address references at link time, when possible; uses the
  linker option @option{-relax}.
  
 -@item -mbigtable
 -@opindex mbigtable
 -Use 32-bit offsets in @code{switch} tables.  The default is to use
 -16-bit offsets.
 -
  @item -mfmovd
  @opindex mfmovd
  Enable the use of the instruction @code{fmovd}.
 --- gcc-HEAD/gcc/config/sh/sh-protos.h	Mon Feb 25 11:27:19 2002
 +++ gcc/gcc/config/sh/sh-protos.h	Mon Feb 25 11:42:25 2002
 @@ -74,6 +74,7 @@
  extern int shl_sext_length PARAMS ((rtx));
  extern int gen_shl_sext PARAMS ((rtx, rtx, rtx, rtx));
  extern rtx gen_datalabel_ref PARAMS ((rtx));
 +extern int shl_casesi_worker_length PARAMS ((rtx));
  extern int regs_used PARAMS ((rtx, int));
  extern void fixup_addr_diff_vecs PARAMS ((rtx));
  extern int get_dest_uid PARAMS ((rtx, int));
 --- gcc-HEAD/gcc/config/sh/sh.c	Mon Feb 25 11:27:19 2002
 +++ gcc/gcc/config/sh/sh.c	Mon Feb 25 11:46:02 2002
 @@ -2143,6 +2143,48 @@
    return sym;
  }
  
 +
 +/* Function to be used in the length attribute of the casesi_worker
 +   instruction.  Returns number of instructions, which is half of the
 +   length of bytes. */
 +
 +int
 +shl_casesi_worker_length (insn)
 +     rtx insn;
 +{
 +  rtx set_src, label;
 +  rtx diff_vec;
 +
 +  set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
 +  if (!(GET_CODE (set_src) == UNSPEC
 +	&& XINT (set_src, 1) == UNSPEC_CASESI))
 +    abort ();
 +
 +  label = XVECEXP (set_src, 0, 2);
 +  if (GET_CODE (label) != LABEL_REF)
 +    abort ();
 +
 +  diff_vec = PATTERN (next_real_insn (XEXP (label, 0)));
 +
 +  if (GET_CODE (diff_vec) != ADDR_DIFF_VEC)
 +    abort ();
 +
 +  switch (GET_MODE (diff_vec))
 +    {
 +    case SImode:
 +      return 2;
 +    case HImode:
 +      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
 +	return 3;
 +      return 2;
 +    case QImode:
 +      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
 +	return 2;
 +      return 1;
 +    default:
 +      abort ();
 +    }
 +}
  
  /* The SH cannot load a large constant into a register, constants have to
     come from a pc relative load.  The reference of a pc relative load
 --- gcc-HEAD/gcc/config/sh/sh.h	Mon Feb 25 11:27:19 2002
 +++ gcc/gcc/config/sh/sh.h	Mon Feb 25 11:56:10 2002
 @@ -234,9 +238,6 @@
  /* Nonzero if we should generate smaller code rather than faster code.  */
  #define TARGET_SMALLCODE   (target_flags & SPACE_BIT)
  
 -/* Nonzero to use long jump tables.  */
 -#define TARGET_BIGTABLE     (target_flags & BIGTABLE_BIT)
 -
  /* Nonzero to generate pseudo-ops needed by the assembler and linker
     to do function call relaxing.  */
  #define TARGET_RELAX (target_flags & RELAX_BIT)
 @@ -297,7 +298,6 @@
    {"5-compact-nofpu", TARGET_NONE, "" },	\
    {"5-compact-nofpu", SH5_BIT|SH3_BIT|SH2_BIT|SH1_BIT, "Generate FPU-less SHcompact code" }, \
    {"b",		-LITTLE_ENDIAN_BIT, "" },  	\
 -  {"bigtable", 	BIGTABLE_BIT, "" },		\
    {"dalign",  	DALIGN_BIT, "" },		\
    {"fmovd",  	FMOVD_BIT, "" },		\
    {"hitachi",	HITACHI_BIT, "" },		\
 @@ -2493,16 +2494,22 @@
      goto LABEL;								\
  }
  
 +extern int optimize; /* needed for gen_casesi.  */
 +extern int optimize_size;
 +
  /* Specify the machine mode that this machine uses
     for the index in the tablejump instruction.  */
 -#define CASE_VECTOR_MODE (TARGET_BIGTABLE ? SImode : HImode)
 +#define CASE_VECTOR_MODE SImode
  
  #define CASE_VECTOR_SHORTEN_MODE(MIN_OFFSET, MAX_OFFSET, BODY) \
  ((MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 127 \
   ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, QImode) \
   : (MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 255 \
   ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, QImode) \
 - : (MIN_OFFSET) >= -32768 && (MAX_OFFSET) <= 32767 ? HImode \
 + : (MIN_OFFSET) >= -32768 && (MAX_OFFSET) <= 32767 \
 + ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 0, HImode) \
 + : optimize_size && (MIN_OFFSET) >= 0 && (MAX_OFFSET) <= 65535 \
 + ? (ADDR_DIFF_VEC_FLAGS (BODY).offset_unsigned = 1, HImode) \
   : SImode)
  
  /* Define as C expression which evaluates to nonzero if the tablejump
 @@ -3038,10 +3045,7 @@
  /* Output an absolute table element.  */
  
  #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM,VALUE)  				\
 -  if (TARGET_BIGTABLE) 							\
 -    asm_fprintf ((STREAM), "\t.long\t%LL%d\n", (VALUE)); 			\
 -  else									\
 -    asm_fprintf ((STREAM), "\t.word\t%LL%d\n", (VALUE)); 			\
 +    asm_fprintf ((STREAM), "\t.long\t%LL%d\n", (VALUE))
  
  /* Output various types of constants.  */
  
 @@ -3166,8 +3170,6 @@
  
  #define sh_cpu_attr ((enum attr_cpu)sh_cpu)
  extern enum processor_type sh_cpu;
 -
 -extern int optimize; /* needed for gen_casesi.  */
  
  enum mdep_reorg_phase_e
  {
 --- gcc-HEAD/gcc/config/sh/sh.md	Mon Feb 25 11:27:19 2002
 +++ gcc/gcc/config/sh/sh.md	Mon Feb 25 11:49:04 2002
 @@ -6446,6 +6446,8 @@
      case SImode:
        return \"shll2	%1\;mov.l	@(r0,%1),%0\";
      case HImode:
 +      if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
 +	return \"add	%1,%1\;mov.w	@(r0,%1),%0\;extu.w	%0,%0\";
        return \"add	%1,%1\;mov.w	@(r0,%1),%0\";
      case QImode:
        if (ADDR_DIFF_VEC_FLAGS (diff_vec).offset_unsigned)
 @@ -6455,7 +6457,15 @@
        abort ();
      }
  }"
 -  [(set_attr "length" "4")])
 +  [(set (attr "length")
 +	(cond [(eq (symbol_ref "shl_casesi_worker_length (insn)") (const_int 1))
 +	       (const_string "2")
 +	       (eq (symbol_ref "shl_casesi_worker_length (insn)") (const_int 2))
 +	       (const_string "4")
 +	       ;; Put "match_dup" here so that insn_variable_length_p return 1.
 +	       (ne (match_dup 2) (match_dup 2))
 +	       (const_string "4")]
 +	      (const_string "6")))])
  
  (define_insn "casesi_shift_media"
    [(set (match_operand 0 "arith_reg_operand" "=r")
 -- 


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