[patch] sh: Move predicates to predicates.md.

Kazu Hirata kazu@cs.umass.edu
Mon Apr 4 15:01:00 GMT 2005


Hi,

Attached is a patch to move predicates to predicates.md.

Built sh-elf.  OK to apply?

Kazu Hirata

2005-04-04  Kazu Hirata  <kazu@cs.umass.edu>

	* config/sh/sh.c (general_movsrc_operand,
	general_movdst_operand, arith_reg_operand, arith_reg_dest,
	int_gpr_dest, fp_arith_reg_operand, arith_operand,
	arith_reg_or_0_operand, shmedia_6bit_operand, logical_operand,
	and_operand, fpscr_operand, fpul_operand, symbol_ref_operand,
	commutative_float_operator, noncommutative_float_operator,
	unary_float_operator, binary_float_operator,
	binary_logical_operator, equality_comparison_operator,
	greater_comparison_operator, less_comparison_operator,
	target_reg_operand, target_operand, mextr_bit_offset,
	extend_reg_operand, trunc_hi_operand, extend_reg_or_0_operand,
	general_extend_operand, inqhi_operand, sh_rep_vec, sh_1el_vec,
	sh_const_vec, sh_register_operand, cmpsi_operand,
	unaligned_load_operand): Move to predicates.md.
	* config/sh/sh.h (PREDICATE_CODES, SPECIAL_MODE_PREDICATES,
	any_register_operand): Remove.
	* config/sh/sh.md: Include predicates.md.
	* config/sh/predicates.md: New.

Index: sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.319
diff -u -d -p -r1.319 sh.c
--- sh.c	30 Mar 2005 18:53:32 -0000	1.319
+++ sh.c	4 Apr 2005 14:02:53 -0000
@@ -7409,211 +7409,6 @@ system_reg_operand (rtx op, enum machine
   return 0;
 }
 
-/* Returns 1 if OP can be source of a simple move operation.
-   Same as general_operand, but a LABEL_REF is valid, PRE_DEC is
-   invalid as are subregs of system registers.  */
-
-int
-general_movsrc_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == MEM)
-    {
-      rtx inside = XEXP (op, 0);
-      if (GET_CODE (inside) == CONST)
-	inside = XEXP (inside, 0);
-
-      if (GET_CODE (inside) == LABEL_REF)
-	return 1;
-
-      if (GET_CODE (inside) == PLUS
-	  && GET_CODE (XEXP (inside, 0)) == LABEL_REF
-	  && GET_CODE (XEXP (inside, 1)) == CONST_INT)
-	return 1;
-
-      /* Only post inc allowed.  */
-      if (GET_CODE (inside) == PRE_DEC)
-	return 0;
-    }
-
-  if ((mode == QImode || mode == HImode)
-      && (GET_CODE (op) == SUBREG
-	  && GET_CODE (XEXP (op, 0)) == REG
-	  && system_reg_operand (XEXP (op, 0), mode)))
-    return 0;
-
-  return general_operand (op, mode);
-}
-
-/* Returns 1 if OP can be a destination of a move.
-   Same as general_operand, but no preinc allowed.  */
-
-int
-general_movdst_operand (rtx op, enum machine_mode mode)
-{
-  /* Only pre dec allowed.  */
-  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
-    return 0;
-
-  return general_operand (op, mode);
-}
-
-/* Returns 1 if OP is a normal arithmetic register.  */
-
-int
-arith_reg_operand (rtx op, enum machine_mode mode)
-{
-  if (register_operand (op, mode))
-    {
-      int regno;
-
-      if (GET_CODE (op) == REG)
-	regno = REGNO (op);
-      else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
-	regno = REGNO (SUBREG_REG (op));
-      else
-	return 1;
-
-      return (regno != T_REG && regno != PR_REG
-	      && ! TARGET_REGISTER_P (regno)
-	      && (regno != FPUL_REG || TARGET_SH4)
-	      && regno != MACH_REG && regno != MACL_REG);
-    }
-  return 0;
-}
-
-/* Like above, but for DImode destinations: forbid paradoxical DImode subregs,
-   because this would lead to missing sign extensions when truncating from
-   DImode to SImode.  */
-int
-arith_reg_dest (rtx op, enum machine_mode mode)
-{
-  if (mode == DImode && GET_CODE (op) == SUBREG
-      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8)
-    return 0;
-  return arith_reg_operand (op, mode);
-}
-
-int
-int_gpr_dest (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  enum machine_mode op_mode = GET_MODE (op);
-
-  if (GET_MODE_CLASS (op_mode) != MODE_INT
-      || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD)
-    return 0;
-  if (! reload_completed)
-    return 0;
-  return true_regnum (op) <= LAST_GENERAL_REG;
-}
-
-int
-fp_arith_reg_operand (rtx op, enum machine_mode mode)
-{
-  if (register_operand (op, mode))
-    {
-      int regno;
-
-      if (GET_CODE (op) == REG)
-	regno = REGNO (op);
-      else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
-	regno = REGNO (SUBREG_REG (op));
-      else
-	return 1;
-
-      return (regno >= FIRST_PSEUDO_REGISTER
-	      || FP_REGISTER_P (regno));
-    }
-  return 0;
-}
-
-/* Returns 1 if OP is a valid source operand for an arithmetic insn.  */
-
-int
-arith_operand (rtx op, enum machine_mode mode)
-{
-  if (arith_reg_operand (op, mode))
-    return 1;
-
-  if (TARGET_SHMEDIA)
-    {
-      /* FIXME: We should be checking whether the CONST_INT fits in a
-	 CONST_OK_FOR_I16 here, but this causes reload_cse to crash when
-	 attempting to transform a sequence of two 64-bit sets of the
-	 same register from literal constants into a set and an add,
-	 when the difference is too wide for an add.  */
-      if (GET_CODE (op) == CONST_INT
-	  || EXTRA_CONSTRAINT_C16 (op))
-	return 1;
-      else
-	return 0;
-    }
-  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (op)))
-    return 1;
-
-  return 0;
-}
-
-/* Returns 1 if OP is a valid source operand for a compare insn.  */
-
-int
-arith_reg_or_0_operand (rtx op, enum machine_mode mode)
-{
-  if (arith_reg_operand (op, mode))
-    return 1;
-
-  if (EXTRA_CONSTRAINT_Z (op))
-    return 1;
-
-  return 0;
-}
-
-/* Return 1 if OP is a valid source operand for an SHmedia operation
-   that takes either a register or a 6-bit immediate.  */
-
-int
-shmedia_6bit_operand (rtx op, enum machine_mode mode)
-{
-  return (arith_reg_operand (op, mode)
-	  || (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I06 (INTVAL (op))));
-}
-
-/* Returns 1 if OP is a valid source operand for a logical operation.  */
-
-int
-logical_operand (rtx op, enum machine_mode mode)
-{
-  if (arith_reg_operand (op, mode))
-    return 1;
-
-  if (TARGET_SHMEDIA)
-    {
-      if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I10 (INTVAL (op)))
-	return 1;
-      else
-	return 0;
-    }
-  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K08 (INTVAL (op)))
-    return 1;
-
-  return 0;
-}
-
-int
-and_operand (rtx op, enum machine_mode mode)
-{
-  if (logical_operand (op, mode))
-    return 1;
-
-  /* Check mshflo.l / mshflhi.l opportunities.  */
-  if (TARGET_SHMEDIA
-      && mode == DImode
-      && GET_CODE (op) == CONST_INT
-      && CONST_OK_FOR_J16 (INTVAL (op)))
-    return 1;
-
-  return 0;
-}
-
 /* Nonzero if OP is a floating point value with value 0.0.  */
 
 int
@@ -7662,33 +7457,6 @@ tertiary_reload_operand (rtx op, enum ma
   return code == MEM || (TARGET_SH4 && code == CONST_DOUBLE);
 }
 
-int
-fpscr_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return (GET_CODE (op) == REG
-	  && (REGNO (op) == FPSCR_REG
-	      || (REGNO (op) >= FIRST_PSEUDO_REGISTER
-		  && !(reload_in_progress || reload_completed)))
-	  && GET_MODE (op) == PSImode);
-}
-
-int
-fpul_operand (rtx op, enum machine_mode mode)
-{
-  if (TARGET_SHMEDIA)
-    return fp_arith_reg_operand (op, mode);
-
-  return (GET_CODE (op) == REG
-	  && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER)
-	  && GET_MODE (op) == mode);
-}
-
-int
-symbol_ref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return (GET_CODE (op) == SYMBOL_REF);
-}
-
 /* Return the TLS type for TLS symbols, 0 for otherwise.  */
 int
 tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
@@ -7697,301 +7465,6 @@ tls_symbolic_operand (rtx op, enum machi
     return 0;
   return SYMBOL_REF_TLS_MODEL (op);
 }
-
-int
-commutative_float_operator (rtx op, enum machine_mode mode)
-{
-  if (GET_MODE (op) != mode)
-    return 0;
-  switch (GET_CODE (op))
-    {
-    case PLUS:
-    case MULT:
-      return 1;
-    default:
-      break;
-    }
-  return 0;
-}
-
-int
-noncommutative_float_operator (rtx op, enum machine_mode mode)
-{
-  if (GET_MODE (op) != mode)
-    return 0;
-  switch (GET_CODE (op))
-    {
-    case MINUS:
-    case DIV:
-      return 1;
-    default:
-      break;
-    }
-  return 0;
-}
-
-int
-unary_float_operator (rtx op, enum machine_mode mode)
-{
-  if (GET_MODE (op) != mode)
-    return 0;
-  switch (GET_CODE (op))
-    {
-    case ABS:
-    case NEG:
-    case SQRT:
-      return 1;
-    default:
-      break;
-    }
-  return 0;
-}
-
-int
-binary_float_operator (rtx op, enum machine_mode mode)
-{
-  if (GET_MODE (op) != mode)
-    return 0;
-  switch (GET_CODE (op))
-    {
-    case PLUS:
-    case MINUS:
-    case MULT:
-    case DIV:
-      return 1;
-    default:
-      break;
-    }
-  return 0;
-}
-
-int
-binary_logical_operator (rtx op, enum machine_mode mode)
-{
-  if (GET_MODE (op) != mode)
-    return 0;
-  switch (GET_CODE (op))
-    {
-    case IOR:
-    case AND:
-    case XOR:
-      return 1;
-    default:
-      break;
-    }
-  return 0;
-}
-
-int
-equality_comparison_operator (rtx op, enum machine_mode mode)
-{
-  return ((mode == VOIDmode || GET_MODE (op) == mode)
-	  && (GET_CODE (op) == EQ || GET_CODE (op) == NE));
-}
-
-int
-greater_comparison_operator (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) == mode)
-    return 0;
-  switch (GET_CODE (op))
-    {
-    case GT:
-    case GE:
-    case GTU:
-    case GEU:
-      return 1;
-    default:
-      return 0;
-    }
-}
-
-int
-less_comparison_operator (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) == mode)
-    return 0;
-  switch (GET_CODE (op))
-    {
-    case LT:
-    case LE:
-    case LTU:
-    case LEU:
-      return 1;
-    default:
-      return 0;
-    }
-}
-
-/* Accept pseudos and branch target registers.  */
-int
-target_reg_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != DImode
-      || GET_MODE (op) != DImode)
-    return 0;
-
-  if (GET_CODE (op) == SUBREG)
-    op = XEXP (op, 0);
-
-  if (GET_CODE (op) != REG)
-    return 0;
-
-  /* We must protect ourselves from matching pseudos that are virtual
-     register, because they will eventually be replaced with hardware
-     registers that aren't branch-target registers.  */
-  if (REGNO (op) > LAST_VIRTUAL_REGISTER
-      || TARGET_REGISTER_P (REGNO (op)))
-    return 1;
-
-  return 0;
-}
-
-/* Same as target_reg_operand, except that label_refs and symbol_refs
-   are accepted before reload.  */
-int
-target_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != DImode)
-    return 0;
-
-  if ((GET_MODE (op) == DImode || GET_MODE (op) == VOIDmode)
-      && EXTRA_CONSTRAINT_Csy (op))
-    return ! reload_completed;
-
-  return target_reg_operand (op, mode);
-}
-
-int
-mextr_bit_offset (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  HOST_WIDE_INT i;
-
-  if (GET_CODE (op) != CONST_INT)
-    return 0;
-  i = INTVAL (op);
-  return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0;
-}
-
-int
-extend_reg_operand (rtx op, enum machine_mode mode)
-{
-  return (GET_CODE (op) == TRUNCATE
-	  ? arith_operand
-	  : arith_reg_operand) (op, mode);
-}
-
-int
-trunc_hi_operand (rtx op, enum machine_mode mode)
-{
-  enum machine_mode op_mode = GET_MODE (op);
-
-  if (op_mode != SImode && op_mode != DImode
-      && op_mode != V4HImode && op_mode != V2SImode)
-    return 0;
-  return extend_reg_operand (op, mode);
-}
-
-int
-extend_reg_or_0_operand (rtx op, enum machine_mode mode)
-{
-  return (GET_CODE (op) == TRUNCATE
-	  ? arith_operand
-	  : arith_reg_or_0_operand) (op, mode);
-}
-
-int
-general_extend_operand (rtx op, enum machine_mode mode)
-{
-  return (GET_CODE (op) == TRUNCATE
-	  ? arith_operand
-	  : nonimmediate_operand) (op, mode);
-}
-
-int
-inqhi_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op))
-    return 0;
-  op = XEXP (op, 0);
-  /* Can't use true_regnum here because copy_cost wants to know about
-     SECONDARY_INPUT_RELOAD_CLASS.  */
-  return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op));
-}
-
-int
-sh_rep_vec (rtx v, enum machine_mode mode)
-{
-  int i;
-  rtx x, y;
-
-  if ((GET_CODE (v) != CONST_VECTOR && GET_CODE (v) != PARALLEL)
-      || (GET_MODE (v) != mode && mode != VOIDmode))
-    return 0;
-  i = XVECLEN (v, 0) - 2;
-  x = XVECEXP (v, 0, i + 1);
-  if (GET_MODE_UNIT_SIZE (mode) == 1)
-    {
-      y = XVECEXP (v, 0, i);
-      for (i -= 2; i >= 0; i -= 2)
-	if (! rtx_equal_p (XVECEXP (v, 0, i + 1), x)
-	    || ! rtx_equal_p (XVECEXP (v, 0, i), y))
-	  return 0;
-    }
-  else
-    for (; i >= 0; i--)
-      if (XVECEXP (v, 0, i) != x)
-	return 0;
-  return 1;
-}
-
-/* Determine if V is a constant vector matching MODE with only one element
-   that is not a sign extension.  Two byte-sized elements count as one.  */
-int
-sh_1el_vec (rtx v, enum machine_mode mode)
-{
-  int unit_size;
-  int i, last, least, sign_ix;
-  rtx sign;
-
-  if (GET_CODE (v) != CONST_VECTOR
-      || (GET_MODE (v) != mode && mode != VOIDmode))
-    return 0;
-  /* Determine numbers of last and of least significant elements.  */
-  last = XVECLEN (v, 0) - 1;
-  least = TARGET_LITTLE_ENDIAN ? 0 : last;
-  if (GET_CODE (XVECEXP (v, 0, least)) != CONST_INT)
-    return 0;
-  sign_ix = least;
-  if (GET_MODE_UNIT_SIZE (mode) == 1)
-    sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1;
-  if (GET_CODE (XVECEXP (v, 0, sign_ix)) != CONST_INT)
-    return 0;
-  unit_size = GET_MODE_UNIT_SIZE (GET_MODE (v));
-  sign = (INTVAL (XVECEXP (v, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1)
-	  ? constm1_rtx : const0_rtx);
-  i = XVECLEN (v, 0) - 1;
-  do
-    if (i != least && i != sign_ix && XVECEXP (v, 0, i) != sign)
-      return 0;
-  while (--i);
-  return 1;
-}
-
-int
-sh_const_vec (rtx v, enum machine_mode mode)
-{
-  int i;
-
-  if (GET_CODE (v) != CONST_VECTOR
-      || (GET_MODE (v) != mode && mode != VOIDmode))
-    return 0;
-  i = XVECLEN (v, 0) - 1;
-  for (; i >= 0; i--)
-    if (GET_CODE (XVECEXP (v, 0, i)) != CONST_INT)
-      return 0;
-  return 1;
-}
 
 /* Return the destination address of a branch.  */
 
@@ -9681,25 +9154,6 @@ sh_register_move_cost (enum machine_mode
   return 2 * ((GET_MODE_SIZE (mode) + 3) / 4U);
 }
 
-/* Like register_operand, but take into account that SHMEDIA can use
-   the constant zero like a general register.  */
-int
-sh_register_operand (rtx op, enum machine_mode mode)
-{
-  if (op == CONST0_RTX (mode) && TARGET_SHMEDIA)
-    return 1;
-  return register_operand (op, mode);
-}
-
-int
-cmpsi_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == REG && REGNO (op) == T_REG
-      && GET_MODE (op) == SImode)
-    return 1;
-  return arith_operand (op, mode);
-}
-
 static rtx emit_load_ptr (rtx, rtx);
 
 static rtx
@@ -10014,27 +9468,6 @@ check_use_sfunc_addr (rtx insn, rtx reg)
   abort ();
 }
 
-/* Returns 1 if OP is a MEM that can be source of a simple move operation.  */
-
-int
-unaligned_load_operand (rtx op, enum machine_mode mode)
-{
-  rtx inside;
-
-  if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
-    return 0;
-
-  inside = XEXP (op, 0);
-
-  if (GET_CODE (inside) == POST_INC)
-    inside = XEXP (inside, 0);
-
-  if (GET_CODE (inside) == REG)
-    return 1;
-
-  return 0;
-}
-
 /* This function returns a constant rtx that represents pi / 2**15 in
    SFmode.  it's used to scale SFmode angles, in radians, to a
    fixed-point signed 16.16-bit fraction of a full circle, i.e., 2*pi
Index: sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.262
diff -u -d -p -r1.262 sh.h
--- sh.h	4 Apr 2005 13:55:05 -0000	1.262
+++ sh.h	4 Apr 2005 14:02:56 -0000
@@ -3336,54 +3336,6 @@ extern int rtx_equal_function_value_matt
 #define ADJUST_INSN_LENGTH(X, LENGTH)				\
   (LENGTH) += sh_insn_length_adjustment (X);
 
-/* Define the codes that are matched by predicates in sh.c.  */
-#define PREDICATE_CODES \
-  {"and_operand", {SUBREG, REG, CONST_INT}},				\
-  {"any_register_operand", {SUBREG, REG}},				\
-  {"arith_operand", {SUBREG, REG, CONST_INT}},				\
-  {"arith_reg_dest", {SUBREG, REG}},					\
-  {"arith_reg_operand", {SUBREG, REG}},					\
-  {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}},	\
-  {"binary_float_operator", {PLUS, MINUS, MULT, DIV}},			\
-  {"binary_logical_operator", {AND, IOR, XOR}},				\
-  {"cmpsi_operand", {SUBREG, REG, CONST_INT}},				\
-  {"commutative_float_operator", {PLUS, MULT}},				\
-  {"equality_comparison_operator", {EQ,NE}},				\
-  {"extend_reg_operand", {SUBREG, REG, TRUNCATE}},			\
-  {"extend_reg_or_0_operand", {SUBREG, REG, TRUNCATE, CONST_INT}},	\
-  {"fp_arith_reg_operand", {SUBREG, REG}},				\
-  {"fpscr_operand", {REG}},						\
-  {"fpul_operand", {REG}},						\
-  {"general_extend_operand", {SUBREG, REG, MEM, TRUNCATE}},		\
-  {"general_movsrc_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM, CONST }}, \
-  {"general_movdst_operand", {SUBREG, REG, MEM}},			\
-  {"unaligned_load_operand", {MEM}},					\
-  {"greater_comparison_operator", {GT,GE,GTU,GEU}},			\
-  {"int_gpr_dest", {SUBREG, REG}},					\
-  {"inqhi_operand", {TRUNCATE}},					\
-  {"less_comparison_operator", {LT,LE,LTU,LEU}},			\
-  {"logical_operand", {SUBREG, REG, CONST_INT}},			\
-  {"mextr_bit_offset", {CONST_INT}},					\
-  {"noncommutative_float_operator", {MINUS, DIV}},			\
-  {"shmedia_6bit_operand", {SUBREG, REG, CONST_INT}},			\
-  {"sh_register_operand", {REG, SUBREG, CONST_INT}},			\
-  {"target_reg_operand", {SUBREG, REG}},				\
-  {"target_operand", {SUBREG, REG, LABEL_REF, SYMBOL_REF, CONST, UNSPEC}},\
-  {"trunc_hi_operand", {SUBREG, REG, TRUNCATE}},			\
-  {"sh_const_vec", {CONST_VECTOR}},					\
-  {"sh_1el_vec", {CONST_VECTOR, PARALLEL}},				\
-  {"sh_rep_vec", {CONST_VECTOR, PARALLEL}},				\
-  {"symbol_ref_operand", {SYMBOL_REF}},					\
-  {"unary_float_operator", {ABS, NEG, SQRT}},				\
-
-#define SPECIAL_MODE_PREDICATES \
-  "any_register_operand", \
-  "int_gpr_dest", \
-  "trunc_hi_operand", \
-  /* This line intentionally left blank.  */
-
-#define any_register_operand register_operand
-
 /* Define this macro if it is advisable to hold scalars in registers
    in a wider mode than that declared by the program.  In such cases,
    the value is constrained to be within the bounds of the declared
Index: sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.191
diff -u -d -p -r1.191 sh.md
--- sh.md	23 Mar 2005 00:14:52 -0000	1.191
+++ sh.md	4 Apr 2005 14:03:06 -0000
@@ -538,6 +538,8 @@
   ;; annuled delay slots.
   [(eq_attr "cond_delay_slot" "yes") (and (eq_attr "cond_delay_slot" "yes")
 					(not (eq_attr "cpu" "sh2e"))) (nil)])
+
+(include "predicates.md")
 
 ;; -------------------------------------------------------------------------
 ;; SImode signed integer comparisons
--- /dev/null	2005-03-29 05:55:50.256877624 -0500
+++ predicates.md	2005-04-04 10:01:58.020542480 -0400
@@ -0,0 +1,647 @@
+;; Predicate definitions for Renesas / SuperH SH.
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; TODO: Add a comment here.
+
+(define_predicate "and_operand"
+  (match_code "subreg,reg,const_int")
+{
+  if (logical_operand (op, mode))
+    return 1;
+
+  /* Check mshflo.l / mshflhi.l opportunities.  */
+  if (TARGET_SHMEDIA
+      && mode == DImode
+      && GET_CODE (op) == CONST_INT
+      && CONST_OK_FOR_J16 (INTVAL (op)))
+    return 1;
+
+  return 0;
+})
+
+;; Return what register_operand returns.
+
+(define_special_predicate "any_register_operand"
+  (match_code "subreg,reg")
+{
+  return register_operand (op, mode);
+})
+
+;; Returns 1 if OP is a valid source operand for an arithmetic insn.
+
+(define_predicate "arith_operand"
+  (match_code "subreg,reg,const_int")
+{
+  if (arith_reg_operand (op, mode))
+    return 1;
+
+  if (TARGET_SHMEDIA)
+    {
+      /* FIXME: We should be checking whether the CONST_INT fits in a
+	 CONST_OK_FOR_I16 here, but this causes reload_cse to crash when
+	 attempting to transform a sequence of two 64-bit sets of the
+	 same register from literal constants into a set and an add,
+	 when the difference is too wide for an add.  */
+      if (GET_CODE (op) == CONST_INT
+	  || EXTRA_CONSTRAINT_C16 (op))
+	return 1;
+      else
+	return 0;
+    }
+  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I08 (INTVAL (op)))
+    return 1;
+
+  return 0;
+})
+
+;; Like above, but for DImode destinations: forbid paradoxical DImode
+;; subregs, because this would lead to missing sign extensions when
+;; truncating from DImode to SImode.
+
+(define_predicate "arith_reg_dest"
+  (match_code "subreg,reg")
+{
+  if (mode == DImode && GET_CODE (op) == SUBREG
+      && GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))) < 8)
+    return 0;
+  return arith_reg_operand (op, mode);
+})
+
+;; Returns 1 if OP is a normal arithmetic register.
+
+(define_predicate "arith_reg_operand"
+  (match_code "subreg,reg")
+{
+  if (register_operand (op, mode))
+    {
+      int regno;
+
+      if (GET_CODE (op) == REG)
+	regno = REGNO (op);
+      else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
+	regno = REGNO (SUBREG_REG (op));
+      else
+	return 1;
+
+      return (regno != T_REG && regno != PR_REG
+	      && ! TARGET_REGISTER_P (regno)
+	      && (regno != FPUL_REG || TARGET_SH4)
+	      && regno != MACH_REG && regno != MACL_REG);
+    }
+  return 0;
+})
+
+;; Returns 1 if OP is a valid source operand for a compare insn.
+
+(define_predicate "arith_reg_or_0_operand"
+  (match_code "subreg,reg,const_int,const_vector")
+{
+  if (arith_reg_operand (op, mode))
+    return 1;
+
+  if (EXTRA_CONSTRAINT_Z (op))
+    return 1;
+
+  return 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "binary_float_operator"
+  (match_code "plus,minus,mult,div")
+{
+  if (GET_MODE (op) != mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case PLUS:
+    case MINUS:
+    case MULT:
+    case DIV:
+      return 1;
+    default:
+      break;
+    }
+  return 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "binary_logical_operator"
+  (match_code "and,ior,xor")
+{
+  if (GET_MODE (op) != mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case IOR:
+    case AND:
+    case XOR:
+      return 1;
+    default:
+      break;
+    }
+  return 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "cmpsi_operand"
+  (match_code "subreg,reg,const_int")
+{
+  if (GET_CODE (op) == REG && REGNO (op) == T_REG
+      && GET_MODE (op) == SImode)
+    return 1;
+  return arith_operand (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "commutative_float_operator"
+  (match_code "plus,mult")
+{
+  if (GET_MODE (op) != mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case PLUS:
+    case MULT:
+      return 1;
+    default:
+      break;
+    }
+  return 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "equality_comparison_operator"
+  (match_code "eq,ne")
+{
+  return ((mode == VOIDmode || GET_MODE (op) == mode)
+	  && (GET_CODE (op) == EQ || GET_CODE (op) == NE));
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "extend_reg_operand"
+  (match_code "subreg,reg,truncate")
+{
+  return (GET_CODE (op) == TRUNCATE
+	  ? arith_operand
+	  : arith_reg_operand) (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "extend_reg_or_0_operand"
+  (match_code "subreg,reg,truncate,const_int")
+{
+  return (GET_CODE (op) == TRUNCATE
+	  ? arith_operand
+	  : arith_reg_or_0_operand) (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "fp_arith_reg_operand"
+  (match_code "subreg,reg")
+{
+  if (register_operand (op, mode))
+    {
+      int regno;
+
+      if (GET_CODE (op) == REG)
+	regno = REGNO (op);
+      else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
+	regno = REGNO (SUBREG_REG (op));
+      else
+	return 1;
+
+      return (regno >= FIRST_PSEUDO_REGISTER
+	      || FP_REGISTER_P (regno));
+    }
+  return 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "fpscr_operand"
+  (match_code "reg")
+{
+  return (GET_CODE (op) == REG
+	  && (REGNO (op) == FPSCR_REG
+	      || (REGNO (op) >= FIRST_PSEUDO_REGISTER
+		  && !(reload_in_progress || reload_completed)))
+	  && GET_MODE (op) == PSImode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "fpul_operand"
+  (match_code "reg")
+{
+  if (TARGET_SHMEDIA)
+    return fp_arith_reg_operand (op, mode);
+
+  return (GET_CODE (op) == REG
+	  && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER)
+	  && GET_MODE (op) == mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "general_extend_operand"
+  (match_code "subreg,reg,mem,truncate")
+{
+  return (GET_CODE (op) == TRUNCATE
+	  ? arith_operand
+	  : nonimmediate_operand) (op, mode);
+})
+
+;; Returns 1 if OP can be source of a simple move operation. Same as
+;; general_operand, but a LABEL_REF is valid, PRE_DEC is invalid as
+;; are subregs of system registers.
+
+(define_predicate "general_movsrc_operand"
+  (match_code "subreg,reg,const_int,const_double,mem,symbol_ref,const")
+{
+  if (GET_CODE (op) == MEM)
+    {
+      rtx inside = XEXP (op, 0);
+      if (GET_CODE (inside) == CONST)
+	inside = XEXP (inside, 0);
+
+      if (GET_CODE (inside) == LABEL_REF)
+	return 1;
+
+      if (GET_CODE (inside) == PLUS
+	  && GET_CODE (XEXP (inside, 0)) == LABEL_REF
+	  && GET_CODE (XEXP (inside, 1)) == CONST_INT)
+	return 1;
+
+      /* Only post inc allowed.  */
+      if (GET_CODE (inside) == PRE_DEC)
+	return 0;
+    }
+
+  if ((mode == QImode || mode == HImode)
+      && (GET_CODE (op) == SUBREG
+	  && GET_CODE (XEXP (op, 0)) == REG
+	  && system_reg_operand (XEXP (op, 0), mode)))
+    return 0;
+
+  return general_operand (op, mode);
+})
+
+;; Returns 1 if OP can be a destination of a move. Same as
+;; general_operand, but no preinc allowed.
+
+(define_predicate "general_movdst_operand"
+  (match_code "subreg,reg,mem")
+{
+  /* Only pre dec allowed.  */
+  if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
+    return 0;
+
+  return general_operand (op, mode);
+})
+
+;; Returns 1 if OP is a MEM that can be source of a simple move
+;; operation.
+
+(define_predicate "unaligned_load_operand"
+  (match_code "mem")
+{
+  rtx inside;
+
+  if (GET_CODE (op) != MEM || GET_MODE (op) != mode)
+    return 0;
+
+  inside = XEXP (op, 0);
+
+  if (GET_CODE (inside) == POST_INC)
+    inside = XEXP (inside, 0);
+
+  if (GET_CODE (inside) == REG)
+    return 1;
+
+  return 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "greater_comparison_operator"
+  (match_code "gt,ge,gtu,geu")
+{
+  if (mode != VOIDmode && GET_MODE (op) == mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case GT:
+    case GE:
+    case GTU:
+    case GEU:
+      return 1;
+    default:
+      return 0;
+    }
+})
+
+;; TODO: Add a comment here.
+
+(define_special_predicate "int_gpr_dest"
+  (match_code "subreg,reg")
+{
+  enum machine_mode op_mode = GET_MODE (op);
+
+  if (GET_MODE_CLASS (op_mode) != MODE_INT
+      || GET_MODE_SIZE (op_mode) >= UNITS_PER_WORD)
+    return 0;
+  if (! reload_completed)
+    return 0;
+  return true_regnum (op) <= LAST_GENERAL_REG;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "inqhi_operand"
+  (match_code "truncate")
+{
+  if (GET_CODE (op) != TRUNCATE || mode != GET_MODE (op))
+    return 0;
+  op = XEXP (op, 0);
+  /* Can't use true_regnum here because copy_cost wants to know about
+     SECONDARY_INPUT_RELOAD_CLASS.  */
+  return GET_CODE (op) == REG && FP_REGISTER_P (REGNO (op));
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "less_comparison_operator"
+  (match_code "lt,le,ltu,leu")
+{
+  if (mode != VOIDmode && GET_MODE (op) == mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case LT:
+    case LE:
+    case LTU:
+    case LEU:
+      return 1;
+    default:
+      return 0;
+    }
+})
+
+;; Returns 1 if OP is a valid source operand for a logical operation.
+
+(define_predicate "logical_operand"
+  (match_code "subreg,reg,const_int")
+{
+  if (arith_reg_operand (op, mode))
+    return 1;
+
+  if (TARGET_SHMEDIA)
+    {
+      if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I10 (INTVAL (op)))
+	return 1;
+      else
+	return 0;
+    }
+  else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_K08 (INTVAL (op)))
+    return 1;
+
+  return 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "mextr_bit_offset"
+  (match_code "const_int")
+{
+  HOST_WIDE_INT i;
+
+  if (GET_CODE (op) != CONST_INT)
+    return 0;
+  i = INTVAL (op);
+  return i >= 1 * 8 && i <= 7 * 8 && (i & 7) == 0;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "noncommutative_float_operator"
+  (match_code "minus,div")
+{
+  if (GET_MODE (op) != mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case MINUS:
+    case DIV:
+      return 1;
+    default:
+      break;
+    }
+  return 0;
+})
+
+;; Return 1 if OP is a valid source operand for an SHmedia operation
+;; that takes either a register or a 6-bit immediate.
+
+(define_predicate "shmedia_6bit_operand"
+  (match_code "subreg,reg,const_int")
+{
+  return (arith_reg_operand (op, mode)
+	  || (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I06 (INTVAL (op))));
+})
+
+;; Like register_operand, but take into account that SHMEDIA can use
+;; the constant zero like a general register.
+
+(define_predicate "sh_register_operand"
+  (match_code "reg,subreg,const_int")
+{
+  if (op == CONST0_RTX (mode) && TARGET_SHMEDIA)
+    return 1;
+  return register_operand (op, mode);
+})
+
+;; Accept pseudos and branch target registers.
+
+(define_predicate "target_reg_operand"
+  (match_code "subreg,reg")
+{
+  if (mode != DImode
+      || GET_MODE (op) != DImode)
+    return 0;
+
+  if (GET_CODE (op) == SUBREG)
+    op = XEXP (op, 0);
+
+  if (GET_CODE (op) != REG)
+    return 0;
+
+  /* We must protect ourselves from matching pseudos that are virtual
+     register, because they will eventually be replaced with hardware
+     registers that aren't branch-target registers.  */
+  if (REGNO (op) > LAST_VIRTUAL_REGISTER
+      || TARGET_REGISTER_P (REGNO (op)))
+    return 1;
+
+  return 0;
+})
+
+;; Same as target_reg_operand, except that label_refs and symbol_refs
+;; are accepted before reload.
+
+(define_predicate "target_operand"
+  (match_code "subreg,reg,label_ref,symbol_ref,const,unspec")
+{
+  if (mode != DImode)
+    return 0;
+
+  if ((GET_MODE (op) == DImode || GET_MODE (op) == VOIDmode)
+      && EXTRA_CONSTRAINT_Csy (op))
+    return ! reload_completed;
+
+  return target_reg_operand (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_special_predicate "trunc_hi_operand"
+  (match_code "subreg,reg,truncate")
+{
+  enum machine_mode op_mode = GET_MODE (op);
+
+  if (op_mode != SImode && op_mode != DImode
+      && op_mode != V4HImode && op_mode != V2SImode)
+    return 0;
+  return extend_reg_operand (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "sh_const_vec"
+  (match_code "const_vector")
+{
+  int i;
+
+  if (GET_CODE (op) != CONST_VECTOR
+      || (GET_MODE (op) != mode && mode != VOIDmode))
+    return 0;
+  i = XVECLEN (op, 0) - 1;
+  for (; i >= 0; i--)
+    if (GET_CODE (XVECEXP (op, 0, i)) != CONST_INT)
+      return 0;
+  return 1;
+})
+
+;; Determine if V is a constant vector matching MODE with only one
+;; element that is not a sign extension.  Two byte-sized elements
+;; count as one.
+
+(define_predicate "sh_1el_vec"
+  (match_code "const_vector,parallel")
+{
+  int unit_size;
+  int i, last, least, sign_ix;
+  rtx sign;
+
+  if (GET_CODE (op) != CONST_VECTOR
+      || (GET_MODE (op) != mode && mode != VOIDmode))
+    return 0;
+  /* Determine numbers of last and of least significant elements.  */
+  last = XVECLEN (op, 0) - 1;
+  least = TARGET_LITTLE_ENDIAN ? 0 : last;
+  if (GET_CODE (XVECEXP (op, 0, least)) != CONST_INT)
+    return 0;
+  sign_ix = least;
+  if (GET_MODE_UNIT_SIZE (mode) == 1)
+    sign_ix = TARGET_LITTLE_ENDIAN ? 1 : last - 1;
+  if (GET_CODE (XVECEXP (op, 0, sign_ix)) != CONST_INT)
+    return 0;
+  unit_size = GET_MODE_UNIT_SIZE (GET_MODE (op));
+  sign = (INTVAL (XVECEXP (op, 0, sign_ix)) >> (unit_size * BITS_PER_UNIT - 1)
+	  ? constm1_rtx : const0_rtx);
+  i = XVECLEN (op, 0) - 1;
+  do
+    if (i != least && i != sign_ix && XVECEXP (op, 0, i) != sign)
+      return 0;
+  while (--i);
+  return 1;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "sh_rep_vec"
+  (match_code "const_vector,parallel")
+{
+  int i;
+  rtx x, y;
+
+  if ((GET_CODE (op) != CONST_VECTOR && GET_CODE (op) != PARALLEL)
+      || (GET_MODE (op) != mode && mode != VOIDmode))
+    return 0;
+  i = XVECLEN (op, 0) - 2;
+  x = XVECEXP (op, 0, i + 1);
+  if (GET_MODE_UNIT_SIZE (mode) == 1)
+    {
+      y = XVECEXP (op, 0, i);
+      for (i -= 2; i >= 0; i -= 2)
+	if (! rtx_equal_p (XVECEXP (op, 0, i + 1), x)
+	    || ! rtx_equal_p (XVECEXP (op, 0, i), y))
+	  return 0;
+    }
+  else
+    for (; i >= 0; i--)
+      if (XVECEXP (op, 0, i) != x)
+	return 0;
+  return 1;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "symbol_ref_operand"
+  (match_code "symbol_ref")
+{
+  return (GET_CODE (op) == SYMBOL_REF);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "unary_float_operator"
+  (match_code "abs,neg,sqrt")
+{
+  if (GET_MODE (op) != mode)
+    return 0;
+  switch (GET_CODE (op))
+    {
+    case ABS:
+    case NEG:
+    case SQRT:
+      return 1;
+    default:
+      break;
+    }
+  return 0;
+})



More information about the Gcc-patches mailing list