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] h8300 port: Precisely specify length of shift insns.


Hi,

Attached is a patch to precisely specify length of shift insns.

Tested on h8300 port.  Committed.

Kazu Hirata

2002-03-02  Kazu Hirata  <kazu@hxi.com>

	* config/h8300/h8300-protos.h: Add a prototype for
	compute_a_shift_length.
	* config/h8300/h8300.c (h8300_asm_insn_count): New.
	(compute_a_shift_length): Likewise.
	(h8300_adjust_insn_length): Do not adjust insn length of shift
	insns.
	* config/h8300/h8300.md (anonymous shift patterns): Use
	compute_a_shift_length.

Index: h8300-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300-protos.h,v
retrieving revision 1.25
diff -c -r1.25 h8300-protos.h
*** h8300-protos.h	2002/03/01 09:14:08	1.25
--- h8300-protos.h	2002/03/02 12:55:58
***************
*** 27,32 ****
--- 27,33 ----
  /* Declarations for functions used in insn-output.c.  */
  #ifdef RTX_CODE
  extern const char *output_a_shift PARAMS ((rtx *));
+ extern unsigned int compute_a_shift_length PARAMS ((rtx, rtx *));
  extern const char *emit_a_rotate PARAMS ((enum rtx_code, rtx *));
  extern const char *output_simode_bld PARAMS ((int, rtx[]));
  extern void print_operand_address PARAMS ((FILE *, rtx));
Index: h8300.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.c,v
retrieving revision 1.126
diff -c -r1.126 h8300.c
*** h8300.c	2002/03/01 22:07:44	1.126
--- h8300.c	2002/03/02 12:55:59
***************
*** 54,59 ****
--- 54,60 ----
  static void push PARAMS ((FILE *, int));
  static void pop PARAMS ((FILE *, int));
  static const char *cond_string PARAMS ((enum rtx_code));
+ static unsigned int h8300_asm_insn_count PARAMS ((const char *));
  const struct attribute_spec h8300_attribute_table[];
  static tree h8300_handle_fndecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
  static tree h8300_handle_eightbit_data_attribute PARAMS ((tree *, tree, tree, int, bool *));
***************
*** 2863,2868 ****
--- 2864,3023 ----
  	}
      }
  }
+ 
+ static unsigned int
+ h8300_asm_insn_count (const char *template)
+ {
+   unsigned int count = 1;
+ 
+   for (; *template; template++)
+     if (*template == '\n')
+       count++;
+ 
+   return count;
+ }
+ 
+ unsigned int
+ compute_a_shift_length (insn, operands)
+      rtx insn ATTRIBUTE_UNUSED;
+      rtx *operands;
+ {
+   rtx shift = operands[3];
+   enum machine_mode mode = GET_MODE (shift);
+   enum rtx_code code = GET_CODE (shift);
+   enum shift_type shift_type;
+   enum shift_mode shift_mode;
+   struct shift_info info;
+   unsigned int wlength = 0;
+ 
+   switch (mode)
+     {
+     case QImode:
+       shift_mode = QIshift;
+       break;
+     case HImode:
+       shift_mode = HIshift;
+       break;
+     case SImode:
+       shift_mode = SIshift;
+       break;
+     default:
+       abort ();
+     }
+ 
+   switch (code)
+     {
+     case ASHIFTRT:
+       shift_type = SHIFT_ASHIFTRT;
+       break;
+     case LSHIFTRT:
+       shift_type = SHIFT_LSHIFTRT;
+       break;
+     case ASHIFT:
+       shift_type = SHIFT_ASHIFT;
+       break;
+     default:
+       abort ();
+     }
+ 
+   if (GET_CODE (operands[2]) != CONST_INT)
+     {
+       /* Get the assembler code to do one shift.  */
+       get_shift_alg (shift_type, shift_mode, 1, &info);
+ 
+       return (4 + h8300_asm_insn_count (info.shift1)) * 2;
+     }
+   else
+     {
+       int n = INTVAL (operands[2]);
+ 
+       /* If the count is negative, make it 0.  */
+       if (n < 0)
+ 	n = 0;
+       /* If the count is too big, truncate it.
+          ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
+ 	 do the intuitive thing.  */
+       else if ((unsigned int) n > GET_MODE_BITSIZE (mode))
+ 	n = GET_MODE_BITSIZE (mode);
+ 
+       get_shift_alg (shift_type, shift_mode, n, &info);
+ 
+       switch (info.alg)
+ 	{
+ 	case SHIFT_SPECIAL:
+ 	  wlength += h8300_asm_insn_count (info.special);
+ 	  /* Fall through.  */
+ 
+ 	case SHIFT_INLINE:
+ 	  n = info.remainder;
+ 
+ 	  if (info.shift2 != NULL)
+ 	    {
+ 	      wlength += h8300_asm_insn_count (info.shift2) * (n / 2);
+ 	      n = n % 2;
+ 	    }
+ 
+ 	  wlength += h8300_asm_insn_count (info.shift1) * n;
+ 	    
+ 	  return 2 * wlength;
+ 
+ 	case SHIFT_ROT_AND:
+ 	  {
+ 	    int m = GET_MODE_BITSIZE (mode) - n;
+ 
+ 	    /* Not all possibilities of rotate are supported.  They shouldn't
+ 	       be generated, but let's watch for 'em.  */
+ 	    if (info.shift1 == 0)
+ 	      abort ();
+ 
+ 	    if (info.shift2 != NULL)
+ 	      {
+ 		wlength += h8300_asm_insn_count (info.shift2) * (m / 2);
+ 		m = m % 2;
+ 	      }
+ 
+ 	    wlength += h8300_asm_insn_count (info.shift1) * m;
+ 	    
+ 	    /* Now mask off the high bits.  */
+ 	    switch (mode)
+ 	      {
+ 	      case QImode:
+ 		wlength += 1;
+ 		break;
+ 	      case HImode:
+ 		wlength += 2;
+ 		break;
+ 	      case SImode:
+ 		if (TARGET_H8300)
+ 		  abort ();
+ 		wlength += 3;
+ 		break;
+ 	      default:
+ 		abort ();
+ 	      }
+ 	    return 2 * wlength;
+ 	  }
+ 
+ 	case SHIFT_LOOP:
+ 	  /* A loop to shift by a "large" constant value.
+ 	     If we have shift-by-2 insns, use them.  */
+ 	  if (info.shift2 != NULL)
+ 	    {
+ 	      wlength += 3 + h8300_asm_insn_count (info.shift2);
+ 	      if (n % 2)
+ 		wlength += h8300_asm_insn_count (info.shift1);
+ 	    }
+ 	  else
+ 	    {
+ 	      wlength += 3 + h8300_asm_insn_count (info.shift1);
+ 	    }
+ 	  return 2 * wlength;
+ 
+ 	default:
+ 	  abort ();
+ 	}
+     }
+ }
  
  /* A rotation by a non-constant will cause a loop to be generated, in
     which a rotation by one bit is used.  A rotation by a constant,
***************
*** 3434,3483 ****
  	      return 4 - 6;
  	    }
  	}
-     }
- 
-   /* Shifts need various adjustments.  */
-   if (GET_CODE (pat) == PARALLEL
-       && GET_CODE (XVECEXP (pat, 0, 0)) == SET
-       && (GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFTRT
- 	  || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == LSHIFTRT
- 	  || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFT))
-     {
-       rtx src = SET_SRC (XVECEXP (pat, 0, 0));
-       enum machine_mode mode = GET_MODE (src);
-       int shift;
- 
-       if (GET_CODE (XEXP (src, 1)) != CONST_INT)
- 	return 0;
- 
-       shift = INTVAL (XEXP (src, 1));
-       /* According to ANSI, negative shift is undefined.  It is
-          considered to be zero in this case (see function
-          output_a_shift above).  */
-       if (shift < 0)
- 	shift = 0;
- 
-       /* QImode shifts by small constants take one insn
- 	 per shift.  So the adjustment is 20 (md length) -
- 	 # shifts * 2.  */
-       if (mode == QImode && shift <= 4)
- 	return -(20 - shift * 2);
- 
-       /* Similarly for HImode and SImode shifts by small constants on
- 	 the H8/300H and H8/S.  */
-       if ((TARGET_H8300H || TARGET_H8300S)
- 	  && (mode == HImode || mode == SImode) && shift <= 4)
- 	return -(20 - shift * 2);
- 
-       /* HImode shifts by small constants for the H8/300.  */
-       if (mode == HImode && shift <= 4)
- 	return -(20 - (shift * (GET_CODE (src) == ASHIFT ? 2 : 4)));
- 
-       /* SImode shifts by small constants for the H8/300.  */
-       if (mode == SImode && shift <= 2)
- 	return -(20 - (shift * (GET_CODE (src) == ASHIFT ? 6 : 8)));
- 
-       /* XXX ??? Could check for more shift/rotate cases here.  */
      }
  
    /* Rotations need various adjustments.  */
--- 3589,3594 ----
Index: h8300.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.md,v
retrieving revision 1.82
diff -c -r1.82 h8300.md
*** h8300.md	2002/02/27 01:09:50	1.82
--- h8300.md	2002/03/02 12:56:00
***************
*** 1769,1775 ****
     (clobber (match_scratch:QI 4 "=X,&r"))]
    ""
    "* return output_a_shift (operands);"
!   [(set_attr "length" "20")
     (set_attr "cc" "clobber")])
  
  ;; HI BIT SHIFTS
--- 1769,1776 ----
     (clobber (match_scratch:QI 4 "=X,&r"))]
    ""
    "* return output_a_shift (operands);"
!   [(set (attr "length")
! 	(symbol_ref "compute_a_shift_length (insn, operands)"))
     (set_attr "cc" "clobber")])
  
  ;; HI BIT SHIFTS
***************
*** 1803,1809 ****
     (clobber (match_scratch:QI 4 "=X,&r"))]
    ""
    "* return output_a_shift (operands);"
!   [(set_attr "length" "20")
     (set_attr "cc" "clobber")])
  
  ;;  SI BIT SHIFTS
--- 1804,1811 ----
     (clobber (match_scratch:QI 4 "=X,&r"))]
    ""
    "* return output_a_shift (operands);"
!   [(set (attr "length")
! 	(symbol_ref "compute_a_shift_length (insn, operands)"))
     (set_attr "cc" "clobber")])
  
  ;;  SI BIT SHIFTS
***************
*** 1837,1843 ****
     (clobber (match_scratch:QI 4 "=X,&r"))]
    ""
    "* return output_a_shift (operands);"
!   [(set_attr "length" "20")
     (set_attr "cc" "clobber")])
  
  ;; ----------------------------------------------------------------------
--- 1839,1846 ----
     (clobber (match_scratch:QI 4 "=X,&r"))]
    ""
    "* return output_a_shift (operands);"
!   [(set (attr "length")
! 	(symbol_ref "compute_a_shift_length (insn, operands)"))
     (set_attr "cc" "clobber")])
  
  ;; ----------------------------------------------------------------------


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