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] v850: Move predicates to predicates.md.


Hi,

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

Built cc1 for v850-elf.  OK to apply?

p.s.
If you could test this patch on a simulator, that would be greatly
appreciated.

Kazu Hirata

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

	* config/v850/v850-protos.h: Remove the prototypes for
	reg_or_int9_operand, reg_or_const_operand,
	pattern_is_ok_for_prepare, pattern_is_ok_for_dispose,
	reg_or_0_operand, reg_or_int5_operand, call_address_operand,
	movsi_source_operand, power_of_two_operand,
	not_power_of_two_operand, special_symbolref_operand,
	pattern_is_ok_for_prologue, pattern_is_ok_for_epilogue, and
	register_is_ok_for_epilogue.
	* config/v850/v850.c (reg_or_0_operand, reg_or_int5_operand,
	reg_or_int9_operand, reg_or_const_operand,
	call_address_operand, special_symbolref_operand,
	movsi_source_operand, power_of_two_operand,
	not_power_of_two_operand, register_is_ok_for_epilogue,
	pattern_is_ok_for_epilogue, pattern_is_ok_for_prologue,
	pattern_is_ok_for_dispose, pattern_is_ok_for_prepare): Move to
	predicates.md.
	* config/v850/v850.h (PREDICATE_CODES): Remove.
	* config/v850/v850.md: Include predicates.md.
	* config/v850/predicates.md: New.

Index: v850-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850-protos.h,v
retrieving revision 1.24
diff -u -d -p -r1.24 v850-protos.h
--- v850-protos.h	30 Dec 2004 03:08:13 -0000	1.24
+++ v850-protos.h	18 Mar 2005 19:25:51 -0000
@@ -1,5 +1,5 @@
 /* Prototypes for v850.c functions used in the md file & elsewhere.
-   Copyright (C) 1999, 2000, 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -51,23 +51,9 @@ extern void   notice_update_cc          
 extern char * construct_save_jarl           (rtx);
 extern char * construct_restore_jr          (rtx);
 #ifdef HAVE_MACHINE_MODES
-extern int    reg_or_int9_operand           (rtx, Mmode);
-extern int    reg_or_const_operand          (rtx, Mmode);
 extern char * construct_dispose_instruction (rtx);
 extern char * construct_prepare_instruction (rtx);
-extern int    pattern_is_ok_for_prepare     (rtx, Mmode);
-extern int    pattern_is_ok_for_dispose     (rtx, Mmode);
 extern int    ep_memory_operand             (rtx, Mmode, int);
-extern int    reg_or_0_operand              (rtx, Mmode);
-extern int    reg_or_int5_operand           (rtx, Mmode);
-extern int    call_address_operand          (rtx, Mmode);
-extern int    movsi_source_operand          (rtx, Mmode);
-extern int    power_of_two_operand          (rtx, Mmode);
-extern int    not_power_of_two_operand      (rtx, Mmode);
-extern int    special_symbolref_operand     (rtx, Mmode);
-extern int    pattern_is_ok_for_prologue    (rtx, Mmode);
-extern int    pattern_is_ok_for_epilogue    (rtx, Mmode);
-extern int    register_is_ok_for_epilogue   (rtx, Mmode);
 #ifdef TREE_CODE
 extern rtx    function_arg                  (CUMULATIVE_ARGS *, Mmode, tree, int);
 #endif
Index: v850.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850.c,v
retrieving revision 1.97
diff -u -d -p -r1.97 v850.c
--- v850.c	30 Dec 2004 03:08:14 -0000	1.97
+++ v850.c	18 Mar 2005 19:25:51 -0000
@@ -1,5 +1,5 @@
 /* Subroutines for insn-output.c for NEC V850 series
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
@@ -1078,132 +1078,6 @@ ep_memory_operand (rtx op, enum machine_
 
   return FALSE;
 }
-
-/* Return true if OP is either a register or 0 */
-
-int
-reg_or_0_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return INTVAL (op) == 0;
-
-  else if (GET_CODE (op) == CONST_DOUBLE)
-    return CONST_DOUBLE_OK_FOR_G (op);
-
-  else
-    return register_operand (op, mode);
-}
-
-/* Return true if OP is either a register or a signed five bit integer */
-
-int
-reg_or_int5_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return CONST_OK_FOR_J (INTVAL (op));
-
-  else
-    return register_operand (op, mode);
-}
-
-/* Return true if OP is either a register or a signed nine bit integer.  */
-
-int
-reg_or_int9_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return CONST_OK_FOR_O (INTVAL (op));
-
-  return register_operand (op, mode);
-}
-
-/* Return true if OP is either a register or a const integer.  */
-
-int
-reg_or_const_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return TRUE;
-
-  return register_operand (op, mode);
-}
-
-/* Return true if OP is a valid call operand.  */
-
-int
-call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  /* Only registers are valid call operands if TARGET_LONG_CALLS.  */
-  if (TARGET_LONG_CALLS)
-    return GET_CODE (op) == REG;
-  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
-}
-
-int
-special_symbolref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (GET_CODE (op) == CONST
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
-      && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1))))
-    op = XEXP (XEXP (op, 0), 0);
-
-  if (GET_CODE (op) == SYMBOL_REF)
-    return (SYMBOL_REF_FLAGS (op)
-	    & (SYMBOL_FLAG_ZDA | SYMBOL_FLAG_TDA | SYMBOL_FLAG_SDA)) != 0;
-
-  return FALSE;
-}
-
-int
-movsi_source_operand (rtx op, enum machine_mode mode)
-{
-  /* Some constants, as well as symbolic operands
-     must be done with HIGH & LO_SUM patterns.  */
-  if (CONSTANT_P (op)
-      && GET_CODE (op) != HIGH
-      && !(GET_CODE (op) == CONST_INT
-           && (CONST_OK_FOR_J (INTVAL (op))
-               || CONST_OK_FOR_K (INTVAL (op))
-               || CONST_OK_FOR_L (INTVAL (op)))))
-    return special_symbolref_operand (op, mode);
-  else
-    return general_operand (op, mode);
-}
-
-int
-power_of_two_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (GET_CODE (op) != CONST_INT)
-    return 0;
-
-  if (exact_log2 (INTVAL (op)) == -1)
-    return 0;
-  return 1;
-}
-
-int
-not_power_of_two_operand (rtx op, enum machine_mode mode)
-{
-  unsigned int mask;
-
-  if (mode == QImode)
-    mask = 0xff;
-  else if (mode == HImode)
-    mask = 0xffff;
-  else if (mode == SImode)
-    mask = 0xffffffff;
-  else
-    return 0;
-
-  if (GET_CODE (op) != CONST_INT)
-    return 0;
-
-  if (exact_log2 (~INTVAL (op) & mask) == -1)
-    return 0;
-  return 1;
-}
-
 
 /* Substitute memory references involving a pointer, to use the ep pointer,
    taking care to save and preserve the ep.  */
@@ -2366,75 +2240,6 @@ v850_encode_section_info (tree decl, rtx
     v850_encode_data_area (decl, XEXP (rtl, 0));
 }
 
-/* Return true if the given RTX is a register which can be restored
-   by a function epilogue.  */
-int
-register_is_ok_for_epilogue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  /* The save/restore routines can only cope with registers 20 - 31.  */
-  return ((GET_CODE (op) == REG)
-          && (((REGNO (op) >= 20) && REGNO (op) <= 31)));
-}
-
-/* Return nonzero if the given RTX is suitable for collapsing into
-   jump to a function epilogue.  */
-int
-pattern_is_ok_for_epilogue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i;
-  
-  /* If there are no registers to restore then the function epilogue
-     is not suitable.  */
-  if (count <= 2)
-    return 0;
-
-  /* The pattern matching has already established that we are performing a
-     function epilogue and that we are popping at least one register.  We must
-     now check the remaining entries in the vector to make sure that they are
-     also register pops.  There is no good reason why there should ever be
-     anything else in this vector, but being paranoid always helps...
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-        (set (match_operand:SI n "register_is_ok_for_epilogue" "r")
-	  (mem:SI (plus:SI (reg:SI 3) (match_operand:SI n "immediate_operand" "i"))))
-     */
-
-  for (i = 3; i < count; i++)
-    {
-      rtx vector_element = XVECEXP (op, 0, i);
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      if (GET_CODE (vector_element) != SET)
-	return 0;
-      
-      dest = SET_DEST (vector_element);
-      src = SET_SRC (vector_element);
-
-      if (GET_CODE (dest) != REG
-	  || GET_MODE (dest) != SImode
-	  || ! register_is_ok_for_epilogue (dest, SImode)
-	  || GET_CODE (src) != MEM
-	  || GET_MODE (src) != SImode)
-	return 0;
-
-      plus = XEXP (src, 0);
-
-      if (GET_CODE (plus) != PLUS
-	  || GET_CODE (XEXP (plus, 0)) != REG
-	  || GET_MODE (XEXP (plus, 0)) != SImode
-	  || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-	return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a JR instruction to a routine that will perform the equivalent of
    the RTL passed in as an argument.  This RTL is a function epilogue that
    pops registers off the stack and possibly releases some extra stack space
@@ -2552,89 +2357,6 @@ construct_restore_jr (rtx op)
 }
 
 
-/* Return nonzero if the given RTX is suitable for collapsing into
-   a jump to a function prologue.  */
-int
-pattern_is_ok_for_prologue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i; 
-  rtx vector_element;
- 
-  /* If there are no registers to save then the function prologue
-     is not suitable.  */
-  if (count <= 2)
-    return 0;
-
-  /* The pattern matching has already established that we are adjusting the
-     stack and pushing at least one register.  We must now check that the
-     remaining entries in the vector to make sure that they are also register
-     pushes, except for the last entry which should be a CLOBBER of r10.
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-     (set (mem:SI (plus:SI (reg:SI 3)
-      (match_operand:SI 2 "immediate_operand" "i")))
-      (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))
-
-     */
-
-  for (i = 2; i < count - (TARGET_LONG_CALLS ? 2: 1); i++)
-    {
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      vector_element = XVECEXP (op, 0, i);
-      
-      if (GET_CODE (vector_element) != SET)
-	return 0;
-      
-      dest = SET_DEST (vector_element);
-      src = SET_SRC (vector_element);
-
-      if (GET_CODE (dest) != MEM
-	  || GET_MODE (dest) != SImode
-	  || GET_CODE (src) != REG
-	  || GET_MODE (src) != SImode
-	  || ! register_is_ok_for_epilogue (src, SImode))
-	return 0;
-
-      plus = XEXP (dest, 0);
-
-      if ( GET_CODE (plus) != PLUS
-	  || GET_CODE (XEXP (plus, 0)) != REG
-	  || GET_MODE (XEXP (plus, 0)) != SImode
-	  || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-	return 0;
-
-      /* If the register is being pushed somewhere other than the stack
-	 space just acquired by the first operand then abandon this quest.
-	 Note: the test is <= because both values are negative.	 */
-      if (INTVAL (XEXP (plus, 1))
-	  <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
-	{
-	  return 0;
-	}
-    }
-
-  /* Make sure that the last entries in the vector are clobbers.  */
-  for (; i < count; i++)
-    {
-      vector_element = XVECEXP (op, 0, i);
-
-      if (GET_CODE (vector_element) != CLOBBER
-	  || GET_CODE (XEXP (vector_element, 0)) != REG
-	  || !(REGNO (XEXP (vector_element, 0)) == 10
-	       || (TARGET_LONG_CALLS ? (REGNO (XEXP (vector_element, 0)) == 11) : 0 )))
-	return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a JARL instruction to a routine that will perform the equivalent
    of the RTL passed as a parameter.  This RTL is a function prologue that
    saves some of the registers r20 - r31 onto the stack, and possibly acquires
@@ -2946,67 +2668,6 @@ v850_insert_attributes (tree decl, tree 
     }
 }
 
-/* Return nonzero if the given RTX is suitable
-   for collapsing into a DISPOSE instruction.  */
-
-int
-pattern_is_ok_for_dispose (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i;
-  
-  /* If there are no registers to restore then
-     the dispose instruction is not suitable.  */
-  if (count <= 2)
-    return 0;
-
-  /* The pattern matching has already established that we are performing a
-     function epilogue and that we are popping at least one register.  We must
-     now check the remaining entries in the vector to make sure that they are
-     also register pops.  There is no good reason why there should ever be
-     anything else in this vector, but being paranoid always helps...
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-        (set (match_operand:SI n "register_is_ok_for_epilogue" "r")
-	  (mem:SI (plus:SI (reg:SI 3)
-	    (match_operand:SI n "immediate_operand" "i"))))
-     */
-
-  for (i = 3; i < count; i++)
-    {
-      rtx vector_element = XVECEXP (op, 0, i);
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      if (GET_CODE (vector_element) != SET)
-	return 0;
-      
-      dest = SET_DEST (vector_element);
-      src  = SET_SRC (vector_element);
-
-      if (   GET_CODE (dest) != REG
-	  || GET_MODE (dest) != SImode
-	  || ! register_is_ok_for_epilogue (dest, SImode)
-	  || GET_CODE (src) != MEM
-	  || GET_MODE (src) != SImode)
-	return 0;
-
-      plus = XEXP (src, 0);
-
-      if (   GET_CODE (plus) != PLUS
-	  || GET_CODE (XEXP (plus, 0)) != REG
-	  || GET_MODE (XEXP (plus, 0)) != SImode
-	  || REGNO    (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-	return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a DISPOSE instruction that is the equivalent of
    the given RTX.  We have already verified that this should
    be possible.  */
@@ -3133,75 +2794,6 @@ construct_dispose_instruction (rtx op)
   return buff;
 }
 
-/* Return nonzero if the given RTX is suitable
-   for collapsing into a PREPARE instruction.  */
-
-int
-pattern_is_ok_for_prepare (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  int count = XVECLEN (op, 0);
-  int i;
-  
-  /* If there are no registers to restore then the prepare instruction
-     is not suitable.  */
-  if (count <= 1)
-    return 0;
-
-  /* The pattern matching has already established that we are adjusting the
-     stack and pushing at least one register.  We must now check that the
-     remaining entries in the vector to make sure that they are also register
-     pushes.
-
-     The test below performs the C equivalent of this machine description
-     pattern match:
-
-     (set (mem:SI (plus:SI (reg:SI 3)
-       (match_operand:SI 2 "immediate_operand" "i")))
-         (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))
-
-     */
-
-  for (i = 2; i < count; i++)
-    {
-      rtx vector_element = XVECEXP (op, 0, i);
-      rtx dest;
-      rtx src;
-      rtx plus;
-      
-      if (GET_CODE (vector_element) != SET)
-	return 0;
-      
-      dest = SET_DEST (vector_element);
-      src  = SET_SRC (vector_element);
-
-      if (   GET_CODE (dest) != MEM
-	  || GET_MODE (dest) != SImode
-	  || GET_CODE (src) != REG
-	  || GET_MODE (src) != SImode
-	  || ! register_is_ok_for_epilogue (src, SImode)
-	     )
-	return 0;
-
-      plus = XEXP (dest, 0);
-
-      if (   GET_CODE (plus) != PLUS
-	  || GET_CODE (XEXP (plus, 0)) != REG
-	  || GET_MODE (XEXP (plus, 0)) != SImode
-	  || REGNO    (XEXP (plus, 0)) != STACK_POINTER_REGNUM
-	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
-	return 0;
-
-      /* If the register is being pushed somewhere other than the stack
-	 space just acquired by the first operand then abandon this quest.
-	 Note: the test is <= because both values are negative.	 */
-      if (INTVAL (XEXP (plus, 1))
-	  <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
-	return 0;
-    }
-
-  return 1;
-}
-
 /* Construct a PREPARE instruction that is the equivalent of
    the given RTL.  We have already verified that this should
    be possible.  */
Index: v850.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850.h,v
retrieving revision 1.101
diff -u -d -p -r1.101 v850.h
--- v850.h	18 Mar 2005 19:01:05 -0000	1.101
+++ v850.h	18 Mar 2005 19:25:51 -0000
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler. NEC V850 series
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    Contributed by Jeff Law (law@cygnus.com).
 
@@ -1368,29 +1368,4 @@ extern union tree_node * GHS_current_sec
 #define SYMBOL_REF_TDA_P(X)	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_TDA) != 0)
 #define SYMBOL_REF_SDA_P(X)	((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_SDA) != 0)
 
-/* Define this if you have defined special-purpose predicates in the
-   file `MACHINE.c'.  This macro is called within an initializer of an
-   array of structures.  The first field in the structure is the name
-   of a predicate and the second field is an array of rtl codes.  For
-   each predicate, list all rtl codes that can be in expressions
-   matched by the predicate.  The list should have a trailing comma.  */
-
-#define PREDICATE_CODES							\
-{ "reg_or_0_operand",		{ REG, SUBREG, CONST_INT, CONST_DOUBLE }}, \
-{ "reg_or_int5_operand",	{ REG, SUBREG, CONST_INT }},		\
-{ "reg_or_int9_operand",	{ REG, SUBREG, CONST_INT }},		\
-{ "reg_or_const_operand",       { REG, CONST_INT }},			\
-{ "call_address_operand",	{ REG, SYMBOL_REF }},			\
-{ "movsi_source_operand",	{ LABEL_REF, SYMBOL_REF, CONST_INT,	\
-				  CONST_DOUBLE, CONST, HIGH, MEM,	\
-				  REG, SUBREG }},			\
-{ "special_symbolref_operand",	{ SYMBOL_REF }},			\
-{ "power_of_two_operand",	{ CONST_INT }},				\
-{ "pattern_is_ok_for_prologue",	{ PARALLEL }},				\
-{ "pattern_is_ok_for_epilogue",	{ PARALLEL }},				\
-{ "register_is_ok_for_epilogue",{ REG }},				\
-{ "pattern_is_ok_for_dispose",	{ PARALLEL }},				\
-{ "pattern_is_ok_for_prepare",	{ PARALLEL }},				\
-{ "not_power_of_two_operand",	{ CONST_INT }},
-  
 #endif /* ! GCC_V850_H */
Index: v850.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/v850/v850.md,v
retrieving revision 1.31
diff -u -d -p -r1.31 v850.md
--- v850.md	18 Aug 2004 21:08:35 -0000	1.31
+++ v850.md	18 Mar 2005 19:25:51 -0000
@@ -1,5 +1,5 @@
 ;; GCC machine description for NEC V850
-;; Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004
+;; Copyright (C) 1996, 1997, 1998, 1999, 2002, 2004, 2005
 ;; Free Software Foundation, Inc.
 ;; Contributed by Jeff Law (law@cygnus.com).
 
@@ -71,6 +71,8 @@
 (define_insn_reservation "v850_memory" 2
 			 (eq_attr "type" "load")
 			 "nothing")
+
+(include "predicates.md")
 
 ;; ----------------------------------------------------------------------
 ;; MOVE INSTRUCTIONS
--- /dev/null	2005-03-04 04:24:27.812945112 -0500
+++ predicates.md	2005-03-18 14:13:39.000000000 -0500
@@ -0,0 +1,439 @@
+;; Predicate definitions for NEC V850.
+;; 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.
+
+;; Return true if OP is either a register or 0.
+
+(define_predicate "reg_or_0_operand"
+  (match_code "reg,subreg,const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_INT)
+    return INTVAL (op) == 0;
+
+  else if (GET_CODE (op) == CONST_DOUBLE)
+    return CONST_DOUBLE_OK_FOR_G (op);
+
+  else
+    return register_operand (op, mode);
+})
+
+;; Return true if OP is either a register or a signed five bit
+;; integer.
+
+(define_predicate "reg_or_int5_operand"
+  (match_code "reg,subreg,const_int")
+{
+  if (GET_CODE (op) == CONST_INT)
+    return CONST_OK_FOR_J (INTVAL (op));
+
+  else
+    return register_operand (op, mode);
+})
+
+;; Return true if OP is either a register or a signed nine bit
+;; integer.
+
+(define_predicate "reg_or_int9_operand"
+  (match_code "reg,subreg,const_int")
+{
+  if (GET_CODE (op) == CONST_INT)
+    return CONST_OK_FOR_O (INTVAL (op));
+
+  return register_operand (op, mode);
+})
+
+;; Return true if OP is either a register or a const integer.
+
+(define_predicate "reg_or_const_operand"
+  (match_code "reg,const_int")
+{
+  if (GET_CODE (op) == CONST_INT)
+    return TRUE;
+
+  return register_operand (op, mode);
+})
+
+;; Return true if OP is a valid call operand.
+
+(define_predicate "call_address_operand"
+  (match_code "reg,symbol_ref")
+{
+  /* Only registers are valid call operands if TARGET_LONG_CALLS.  */
+  if (TARGET_LONG_CALLS)
+    return GET_CODE (op) == REG;
+  return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "movsi_source_operand"
+  (match_code "label_ref,symbol_ref,const_int,const_double,const,high,mem,reg,subreg")
+{
+  /* Some constants, as well as symbolic operands
+     must be done with HIGH & LO_SUM patterns.  */
+  if (CONSTANT_P (op)
+      && GET_CODE (op) != HIGH
+      && !(GET_CODE (op) == CONST_INT
+           && (CONST_OK_FOR_J (INTVAL (op))
+               || CONST_OK_FOR_K (INTVAL (op))
+               || CONST_OK_FOR_L (INTVAL (op)))))
+    return special_symbolref_operand (op, mode);
+  else
+    return general_operand (op, mode);
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "special_symbolref_operand"
+  (match_code "symbol_ref")
+{
+  if (GET_CODE (op) == CONST
+      && GET_CODE (XEXP (op, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
+      && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1))))
+    op = XEXP (XEXP (op, 0), 0);
+
+  if (GET_CODE (op) == SYMBOL_REF)
+    return (SYMBOL_REF_FLAGS (op)
+	    & (SYMBOL_FLAG_ZDA | SYMBOL_FLAG_TDA | SYMBOL_FLAG_SDA)) != 0;
+
+  return FALSE;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "power_of_two_operand"
+  (match_code "const_int")
+{
+  if (GET_CODE (op) != CONST_INT)
+    return 0;
+
+  if (exact_log2 (INTVAL (op)) == -1)
+    return 0;
+  return 1;
+})
+
+;; Return nonzero if the given RTX is suitable for collapsing into a
+;; jump to a function prologue.
+
+(define_predicate "pattern_is_ok_for_prologue"
+  (match_code "parallel")
+{
+  int count = XVECLEN (op, 0);
+  int i;
+  rtx vector_element;
+
+  /* If there are no registers to save then the function prologue
+     is not suitable.  */
+  if (count <= 2)
+    return 0;
+
+  /* The pattern matching has already established that we are adjusting the
+     stack and pushing at least one register.  We must now check that the
+     remaining entries in the vector to make sure that they are also register
+     pushes, except for the last entry which should be a CLOBBER of r10.
+
+     The test below performs the C equivalent of this machine description
+     pattern match:
+
+     (set (mem:SI (plus:SI (reg:SI 3)
+      (match_operand:SI 2 "immediate_operand" "i")))
+      (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))
+
+     */
+
+  for (i = 2; i < count - (TARGET_LONG_CALLS ? 2: 1); i++)
+    {
+      rtx dest;
+      rtx src;
+      rtx plus;
+
+      vector_element = XVECEXP (op, 0, i);
+
+      if (GET_CODE (vector_element) != SET)
+	return 0;
+
+      dest = SET_DEST (vector_element);
+      src = SET_SRC (vector_element);
+
+      if (GET_CODE (dest) != MEM
+	  || GET_MODE (dest) != SImode
+	  || GET_CODE (src) != REG
+	  || GET_MODE (src) != SImode
+	  || ! register_is_ok_for_epilogue (src, SImode))
+	return 0;
+
+      plus = XEXP (dest, 0);
+
+      if ( GET_CODE (plus) != PLUS
+	  || GET_CODE (XEXP (plus, 0)) != REG
+	  || GET_MODE (XEXP (plus, 0)) != SImode
+	  || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
+	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
+	return 0;
+
+      /* If the register is being pushed somewhere other than the stack
+	 space just acquired by the first operand then abandon this quest.
+	 Note: the test is <= because both values are negative.	 */
+      if (INTVAL (XEXP (plus, 1))
+	  <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
+	{
+	  return 0;
+	}
+    }
+
+  /* Make sure that the last entries in the vector are clobbers.  */
+  for (; i < count; i++)
+    {
+      vector_element = XVECEXP (op, 0, i);
+
+      if (GET_CODE (vector_element) != CLOBBER
+	  || GET_CODE (XEXP (vector_element, 0)) != REG
+	  || !(REGNO (XEXP (vector_element, 0)) == 10
+	       || (TARGET_LONG_CALLS ? (REGNO (XEXP (vector_element, 0)) == 11) : 0 )))
+	return 0;
+    }
+
+  return 1;
+})
+
+;; Return nonzero if the given RTX is suitable for collapsing into
+;; jump to a function epilogue.
+
+(define_predicate "pattern_is_ok_for_epilogue"
+  (match_code "parallel")
+{
+  int count = XVECLEN (op, 0);
+  int i;
+
+  /* If there are no registers to restore then the function epilogue
+     is not suitable.  */
+  if (count <= 2)
+    return 0;
+
+  /* The pattern matching has already established that we are performing a
+     function epilogue and that we are popping at least one register.  We must
+     now check the remaining entries in the vector to make sure that they are
+     also register pops.  There is no good reason why there should ever be
+     anything else in this vector, but being paranoid always helps...
+
+     The test below performs the C equivalent of this machine description
+     pattern match:
+
+        (set (match_operand:SI n "register_is_ok_for_epilogue" "r")
+	  (mem:SI (plus:SI (reg:SI 3) (match_operand:SI n "immediate_operand" "i"))))
+     */
+
+  for (i = 3; i < count; i++)
+    {
+      rtx vector_element = XVECEXP (op, 0, i);
+      rtx dest;
+      rtx src;
+      rtx plus;
+
+      if (GET_CODE (vector_element) != SET)
+	return 0;
+
+      dest = SET_DEST (vector_element);
+      src = SET_SRC (vector_element);
+
+      if (GET_CODE (dest) != REG
+	  || GET_MODE (dest) != SImode
+	  || ! register_is_ok_for_epilogue (dest, SImode)
+	  || GET_CODE (src) != MEM
+	  || GET_MODE (src) != SImode)
+	return 0;
+
+      plus = XEXP (src, 0);
+
+      if (GET_CODE (plus) != PLUS
+	  || GET_CODE (XEXP (plus, 0)) != REG
+	  || GET_MODE (XEXP (plus, 0)) != SImode
+	  || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM
+	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
+	return 0;
+    }
+
+  return 1;
+})
+
+;; Return true if the given RTX is a register which can be restored by
+;; a function epilogue.
+
+(define_predicate "register_is_ok_for_epilogue"
+  (match_code "reg")
+{
+  /* The save/restore routines can only cope with registers 20 - 31.  */
+  return ((GET_CODE (op) == REG)
+          && (((REGNO (op) >= 20) && REGNO (op) <= 31)));
+})
+
+;; Return nonzero if the given RTX is suitable for collapsing into a
+;; DISPOSE instruction.
+
+(define_predicate "pattern_is_ok_for_dispose"
+  (match_code "parallel")
+{
+  int count = XVECLEN (op, 0);
+  int i;
+
+  /* If there are no registers to restore then
+     the dispose instruction is not suitable.  */
+  if (count <= 2)
+    return 0;
+
+  /* The pattern matching has already established that we are performing a
+     function epilogue and that we are popping at least one register.  We must
+     now check the remaining entries in the vector to make sure that they are
+     also register pops.  There is no good reason why there should ever be
+     anything else in this vector, but being paranoid always helps...
+
+     The test below performs the C equivalent of this machine description
+     pattern match:
+
+        (set (match_operand:SI n "register_is_ok_for_epilogue" "r")
+	  (mem:SI (plus:SI (reg:SI 3)
+	    (match_operand:SI n "immediate_operand" "i"))))
+     */
+
+  for (i = 3; i < count; i++)
+    {
+      rtx vector_element = XVECEXP (op, 0, i);
+      rtx dest;
+      rtx src;
+      rtx plus;
+
+      if (GET_CODE (vector_element) != SET)
+	return 0;
+
+      dest = SET_DEST (vector_element);
+      src  = SET_SRC (vector_element);
+
+      if (   GET_CODE (dest) != REG
+	  || GET_MODE (dest) != SImode
+	  || ! register_is_ok_for_epilogue (dest, SImode)
+	  || GET_CODE (src) != MEM
+	  || GET_MODE (src) != SImode)
+	return 0;
+
+      plus = XEXP (src, 0);
+
+      if (   GET_CODE (plus) != PLUS
+	  || GET_CODE (XEXP (plus, 0)) != REG
+	  || GET_MODE (XEXP (plus, 0)) != SImode
+	  || REGNO    (XEXP (plus, 0)) != STACK_POINTER_REGNUM
+	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
+	return 0;
+    }
+
+  return 1;
+})
+
+;; Return nonzero if the given RTX is suitable for collapsing into a
+;; PREPARE instruction.
+
+(define_predicate "pattern_is_ok_for_prepare"
+  (match_code "parallel")
+{
+  int count = XVECLEN (op, 0);
+  int i;
+
+  /* If there are no registers to restore then the prepare instruction
+     is not suitable.  */
+  if (count <= 1)
+    return 0;
+
+  /* The pattern matching has already established that we are adjusting the
+     stack and pushing at least one register.  We must now check that the
+     remaining entries in the vector to make sure that they are also register
+     pushes.
+
+     The test below performs the C equivalent of this machine description
+     pattern match:
+
+     (set (mem:SI (plus:SI (reg:SI 3)
+       (match_operand:SI 2 "immediate_operand" "i")))
+         (match_operand:SI 3 "register_is_ok_for_epilogue" "r"))
+
+     */
+
+  for (i = 2; i < count; i++)
+    {
+      rtx vector_element = XVECEXP (op, 0, i);
+      rtx dest;
+      rtx src;
+      rtx plus;
+
+      if (GET_CODE (vector_element) != SET)
+	return 0;
+
+      dest = SET_DEST (vector_element);
+      src  = SET_SRC (vector_element);
+
+      if (   GET_CODE (dest) != MEM
+	  || GET_MODE (dest) != SImode
+	  || GET_CODE (src) != REG
+	  || GET_MODE (src) != SImode
+	  || ! register_is_ok_for_epilogue (src, SImode)
+	     )
+	return 0;
+
+      plus = XEXP (dest, 0);
+
+      if (   GET_CODE (plus) != PLUS
+	  || GET_CODE (XEXP (plus, 0)) != REG
+	  || GET_MODE (XEXP (plus, 0)) != SImode
+	  || REGNO    (XEXP (plus, 0)) != STACK_POINTER_REGNUM
+	  || GET_CODE (XEXP (plus, 1)) != CONST_INT)
+	return 0;
+
+      /* If the register is being pushed somewhere other than the stack
+	 space just acquired by the first operand then abandon this quest.
+	 Note: the test is <= because both values are negative.	 */
+      if (INTVAL (XEXP (plus, 1))
+	  <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)))
+	return 0;
+    }
+
+  return 1;
+})
+
+;; TODO: Add a comment here.
+
+(define_predicate "not_power_of_two_operand"
+  (match_code "const_int")
+{
+  unsigned int mask;
+
+  if (mode == QImode)
+    mask = 0xff;
+  else if (mode == HImode)
+    mask = 0xffff;
+  else if (mode == SImode)
+    mask = 0xffffffff;
+  else
+    return 0;
+
+  if (GET_CODE (op) != CONST_INT)
+    return 0;
+
+  if (exact_log2 (~INTVAL (op) & mask) == -1)
+    return 0;
+  return 1;
+})


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