diff gcc/config/arm/predicates.md @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents f6334be47118
children 84e7813d76e9
line wrap: on
line diff
--- a/gcc/config/arm/predicates.md	Sun Aug 21 07:07:55 2011 +0900
+++ b/gcc/config/arm/predicates.md	Fri Oct 27 22:46:09 2017 +0900
@@ -1,5 +1,5 @@
 ;; Predicate definitions for ARM and Thumb
-;; Copyright (C) 2004, 2007, 2008, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 2004-2017 Free Software Foundation, Inc.
 ;; Contributed by ARM Ltd.
 
 ;; This file is part of GCC.
@@ -26,16 +26,38 @@
   /* We don't consider registers whose class is NO_REGS
      to be a register operand.  */
   /* XXX might have to check for lo regs only for thumb ??? */
-  return (GET_CODE (op) == REG
+  return (REG_P (op)
 	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER
 	      || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
 })
 
-;; Any hard register.
-(define_predicate "arm_hard_register_operand"
+(define_predicate "imm_for_neon_inv_logic_operand"
+  (match_code "const_vector")
+{
+  return (TARGET_NEON
+          && neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL));
+})
+
+(define_predicate "neon_inv_logic_op2"
+  (ior (match_operand 0 "imm_for_neon_inv_logic_operand")
+       (match_operand 0 "s_register_operand")))
+
+(define_predicate "imm_for_neon_logic_operand"
+  (match_code "const_vector")
+{
+  return (TARGET_NEON
+          && neon_immediate_valid_for_logic (op, mode, 0, NULL, NULL));
+})
+
+(define_predicate "neon_logic_op2"
+  (ior (match_operand 0 "imm_for_neon_logic_operand")
+       (match_operand 0 "s_register_operand")))
+
+;; Any general register.
+(define_predicate "arm_hard_general_register_operand"
   (match_code "reg")
 {
-  return REGNO (op) < FIRST_PSEUDO_REGISTER;
+  return REGNO (op) <= LAST_ARM_REGNUM;
 })
 
 ;; A low register.
@@ -55,23 +77,15 @@
   if (GET_CODE (op) == SUBREG)
     op = SUBREG_REG (op);
 
-  return (GET_CODE (op) == REG
+  return (REG_P (op)
 	  && (REGNO (op) <= LAST_ARM_REGNUM
 	      || REGNO (op) >= FIRST_PSEUDO_REGISTER));
 })
 
-(define_predicate "f_register_operand"
-  (match_code "reg,subreg")
-{
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-
-  /* We don't consider registers whose class is NO_REGS
-     to be a register operand.  */
-  return (GET_CODE (op) == REG
-	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER
-	      || REGNO_REG_CLASS (REGNO (op)) == FPA_REGS));
-})
+(define_predicate "arm_general_adddi_operand"
+  (ior (match_operand 0 "arm_general_register_operand")
+       (and (match_code "const_int")
+	    (match_test "const_ok_for_dimode_op (INTVAL (op), PLUS)"))))
 
 (define_predicate "vfp_register_operand"
   (match_code "reg,subreg")
@@ -81,7 +95,7 @@
 
   /* We don't consider registers whose class is NO_REGS
      to be a register operand.  */
-  return (GET_CODE (op) == REG
+  return (REG_P (op)
 	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER
 	      || REGNO_REG_CLASS (REGNO (op)) == VFP_D0_D7_REGS
 	      || REGNO_REG_CLASS (REGNO (op)) == VFP_LO_REGS
@@ -89,6 +103,21 @@
 		  && REGNO_REG_CLASS (REGNO (op)) == VFP_REGS)));
 })
 
+(define_predicate "vfp_hard_register_operand"
+  (match_code "reg")
+{
+  return (IS_VFP_REGNUM (REGNO (op)));
+})
+
+(define_predicate "zero_operand"
+  (and (match_code "const_int,const_double,const_vector")
+       (match_test "op == CONST0_RTX (mode)")))
+
+;; Match a register, or zero in the appropriate mode.
+(define_predicate "reg_or_zero_operand"
+  (ior (match_operand 0 "s_register_operand")
+       (match_operand 0 "zero_operand")))
+
 (define_special_predicate "subreg_lowpart_operator"
   (and (match_code "subreg")
        (match_test "subreg_lowpart_p (op)")))
@@ -117,8 +146,7 @@
        (match_test "const_ok_for_arm (~INTVAL (op))")))
 
 (define_predicate "const0_operand"
-  (and (match_code "const_int")
-       (match_test "INTVAL (op) == 0")))
+  (match_test "op == CONST0_RTX (mode)"))
 
 ;; Something valid on the RHS of an ARM data-processing instruction
 (define_predicate "arm_rhs_operand"
@@ -129,15 +157,55 @@
   (ior (match_operand 0 "arm_rhs_operand")
        (match_operand 0 "memory_operand")))
 
+(define_predicate "const_int_I_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "satisfies_constraint_I (op)")))
+
+(define_predicate "const_int_M_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "satisfies_constraint_M (op)")))
+
+;; This doesn't have to do much because the constant is already checked
+;; in the shift_operator predicate.
 (define_predicate "shift_amount_operand"
   (ior (and (match_test "TARGET_ARM")
 	    (match_operand 0 "s_register_operand"))
        (match_operand 0 "const_int_operand")))
 
+(define_predicate "const_neon_scalar_shift_amount_operand"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (UINTVAL (op), 1, GET_MODE_BITSIZE (mode))")))
+
+(define_predicate "ldrd_strd_offset_operand"
+  (and (match_operand 0 "const_int_operand")
+       (match_test "TARGET_LDRD && offset_ok_for_ldrd_strd (INTVAL (op))")))
+
 (define_predicate "arm_add_operand"
   (ior (match_operand 0 "arm_rhs_operand")
        (match_operand 0 "arm_neg_immediate_operand")))
 
+(define_predicate "arm_anddi_operand_neon"
+  (ior (match_operand 0 "s_register_operand")
+       (and (match_code "const_int")
+	    (match_test "const_ok_for_dimode_op (INTVAL (op), AND)"))
+       (match_operand 0 "neon_inv_logic_op2")))
+
+(define_predicate "arm_iordi_operand_neon"
+  (ior (match_operand 0 "s_register_operand")
+       (and (match_code "const_int")
+	    (match_test "const_ok_for_dimode_op (INTVAL (op), IOR)"))
+       (match_operand 0 "neon_logic_op2")))
+
+(define_predicate "arm_xordi_operand"
+  (ior (match_operand 0 "s_register_operand")
+       (and (match_code "const_int")
+	    (match_test "const_ok_for_dimode_op (INTVAL (op), XOR)"))))
+
+(define_predicate "arm_adddi_operand"
+  (ior (match_operand 0 "s_register_operand")
+       (and (match_code "const_int")
+	    (match_test "const_ok_for_dimode_op (INTVAL (op), PLUS)"))))
+
 (define_predicate "arm_addimm_operand"
   (ior (match_operand 0 "arm_immediate_operand")
        (match_operand 0 "arm_neg_immediate_operand")))
@@ -170,36 +238,19 @@
   (and (match_code "mem,reg,subreg")
        (match_test "(!CONSTANT_P (op)
 		     && (true_regnum(op) == -1
-			 || (GET_CODE (op) == REG
+			 || (REG_P (op)
 			     && REGNO (op) >= FIRST_PSEUDO_REGISTER)))")))
 
-;; True for valid operands for the rhs of an floating point insns.
-;;   Allows regs or certain consts on FPA, just regs for everything else.
-(define_predicate "arm_float_rhs_operand"
-  (ior (match_operand 0 "s_register_operand")
-       (and (match_code "const_double")
-	    (match_test "TARGET_FPA && arm_const_double_rtx (op)"))))
-
-(define_predicate "arm_float_add_operand"
-  (ior (match_operand 0 "arm_float_rhs_operand")
-       (and (match_code "const_double")
-	    (match_test "TARGET_FPA && neg_const_double_rtx_ok_for_fpa (op)"))))
-
 (define_predicate "vfp_compare_operand"
   (ior (match_operand 0 "s_register_operand")
        (and (match_code "const_double")
 	    (match_test "arm_const_double_rtx (op)"))))
 
-(define_predicate "arm_float_compare_operand"
-  (if_then_else (match_test "TARGET_VFP")
-		(match_operand 0 "vfp_compare_operand")
-		(match_operand 0 "arm_float_rhs_operand")))
-
 ;; True for valid index operands.
 (define_predicate "index_operand"
   (ior (match_operand 0 "s_register_operand")
        (and (match_operand 0 "immediate_operand")
-	    (match_test "(GET_CODE (op) != CONST_INT
+	    (match_test "(!CONST_INT_P (op)
 			  || (INTVAL (op) < 4096 && INTVAL (op) > -4096))"))))
 
 ;; True for operators that can be combined with a shift in ARM state.
@@ -207,6 +258,10 @@
   (and (match_code "plus,minus,ior,xor,and")
        (match_test "mode == GET_MODE (op)")))
 
+(define_special_predicate "shiftable_operator_strict_it"
+  (and (match_code "plus,and")
+       (match_test "mode == GET_MODE (op)")))
+
 ;; True for logical binary operators.
 (define_special_predicate "logical_binary_operator"
   (and (match_code "ior,xor,and")
@@ -218,13 +273,38 @@
        (match_test "mode == GET_MODE (op)")))
 
 ;; True for shift operators.
+;; Notes:
+;;  * mult is only permitted with a constant shift amount
+;;  * patterns that permit register shift amounts only in ARM mode use
+;;    shift_amount_operand, patterns that always allow registers do not,
+;;    so we don't have to worry about that sort of thing here.
 (define_special_predicate "shift_operator"
   (and (ior (ior (and (match_code "mult")
 		      (match_test "power_of_two_operand (XEXP (op, 1), mode)"))
 		 (and (match_code "rotate")
-		      (match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
-				   && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
-	    (match_code "ashift,ashiftrt,lshiftrt,rotatert"))
+		      (match_test "CONST_INT_P (XEXP (op, 1))
+				   && (UINTVAL (XEXP (op, 1))) < 32")))
+	    (and (match_code "ashift,ashiftrt,lshiftrt,rotatert")
+		 (match_test "!CONST_INT_P (XEXP (op, 1))
+			      || (UINTVAL (XEXP (op, 1))) < 32")))
+       (match_test "mode == GET_MODE (op)")))
+
+(define_special_predicate "shift_nomul_operator"
+  (and (ior (and (match_code "rotate")
+		 (match_test "CONST_INT_P (XEXP (op, 1))
+			      && (UINTVAL (XEXP (op, 1))) < 32"))
+	    (and (match_code "ashift,ashiftrt,lshiftrt,rotatert")
+		 (match_test "!CONST_INT_P (XEXP (op, 1))
+			      || (UINTVAL (XEXP (op, 1))) < 32")))
+       (match_test "mode == GET_MODE (op)")))
+
+;; True for shift operators which can be used with saturation instructions.
+(define_special_predicate "sat_shift_operator"
+  (and (ior (and (match_code "mult")
+                 (match_test "power_of_two_operand (XEXP (op, 1), mode)"))
+            (and (match_code "ashift,ashiftrt")
+                 (match_test "CONST_INT_P (XEXP (op, 1))
+		              && (UINTVAL (XEXP (op, 1)) < 32)")))
        (match_test "mode == GET_MODE (op)")))
 
 ;; True for MULT, to identify which variant of shift_operator is in use.
@@ -241,15 +321,44 @@
 
 ;; True for integer comparisons and, if FP is active, for comparisons
 ;; other than LTGT or UNEQ.
+(define_special_predicate "expandable_comparison_operator"
+  (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,
+	       unordered,ordered,unlt,unle,unge,ungt"))
+
+;; Likewise, but only accept comparisons that are directly supported
+;; by ARM condition codes.
 (define_special_predicate "arm_comparison_operator"
-  (ior (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu")
-       (and (match_test "TARGET_32BIT && TARGET_HARD_FLOAT
-			 && (TARGET_FPA || TARGET_VFP)")
-            (match_code "unordered,ordered,unlt,unle,unge,ungt"))))
+  (and (match_operand 0 "expandable_comparison_operator")
+       (match_test "maybe_get_arm_condition_code (op) != ARM_NV")))
+
+;; Likewise, but don't ignore the mode.
+;; RTL SET operations require their operands source and destination have
+;; the same modes, so we can't ignore the modes there.  See PR target/69161.
+(define_predicate "arm_comparison_operator_mode"
+  (and (match_operand 0 "expandable_comparison_operator")
+       (match_test "maybe_get_arm_condition_code (op) != ARM_NV")))
 
 (define_special_predicate "lt_ge_comparison_operator"
   (match_code "lt,ge"))
 
+;; The vsel instruction only accepts the ARM condition codes listed below.
+(define_special_predicate "arm_vsel_comparison_operator"
+  (and (match_operand 0 "expandable_comparison_operator")
+       (match_test "maybe_get_arm_condition_code (op) == ARM_GE
+                    || maybe_get_arm_condition_code (op) == ARM_GT
+                    || maybe_get_arm_condition_code (op) == ARM_EQ
+                    || maybe_get_arm_condition_code (op) == ARM_VS
+                    || maybe_get_arm_condition_code (op) == ARM_LT
+                    || maybe_get_arm_condition_code (op) == ARM_LE
+                    || maybe_get_arm_condition_code (op) == ARM_NE
+                    || maybe_get_arm_condition_code (op) == ARM_VC")))
+
+(define_special_predicate "arm_cond_move_operator"
+  (if_then_else (match_test "arm_restrict_it")
+		(and (match_test "TARGET_VFP5")
+		     (match_operand 0 "arm_vsel_comparison_operator"))
+		(match_operand 0 "expandable_comparison_operator")))
+
 (define_special_predicate "noov_comparison_operator"
   (match_code "lt,ge,eq,ne"))
 
@@ -287,10 +396,19 @@
 	     || mode == CC_DGTUmode));
 })
 
+;; Any register, including CC
+(define_predicate "cc_register_operand"
+  (and (match_code "reg")
+       (ior (match_operand 0 "s_register_operand")
+	    (match_operand 0 "cc_register"))))
+
 (define_special_predicate "arm_extendqisi_mem_op"
   (and (match_operand 0 "memory_operand")
-       (match_test "arm_legitimate_address_outer_p (mode, XEXP (op, 0),
-						    SIGN_EXTEND, 0)")))
+       (match_test "TARGET_ARM ? arm_legitimate_address_outer_p (mode,
+                                                                 XEXP (op, 0),
+						                 SIGN_EXTEND,
+								 0)
+                               : memory_address_p (QImode, XEXP (op, 0))")))
 
 (define_special_predicate "arm_reg_or_extendqisi_mem_op"
   (ior (match_operand 0 "arm_extendqisi_mem_op")
@@ -313,7 +431,7 @@
    if (GET_CODE (op) == SUBREG)
      op = SUBREG_REG (op);
 
-   return GET_CODE (op) == MEM && memory_address_p (DImode, XEXP (op, 0));
+   return MEM_P (op) && memory_address_p (DImode, XEXP (op, 0));
 })
 
 (define_predicate "di_operand"
@@ -330,7 +448,7 @@
   if (GET_CODE (op) == SUBREG)
     op = SUBREG_REG (op);
 
-  return GET_CODE (op) == MEM && memory_address_p (DFmode, XEXP (op, 0));
+  return MEM_P (op) && memory_address_p (DFmode, XEXP (op, 0));
 })
 
 (define_predicate "soft_df_operand"
@@ -338,163 +456,36 @@
        (and (match_code "reg,subreg,mem")
 	    (match_operand 0 "nonimmediate_soft_df_operand"))))
 
-(define_predicate "const_shift_operand"
-  (and (match_code "const_int")
-       (ior (match_operand 0 "power_of_two_operand")
-	    (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 32"))))
-
-
 (define_special_predicate "load_multiple_operation"
   (match_code "parallel")
 {
-  HOST_WIDE_INT count = XVECLEN (op, 0);
-  unsigned dest_regno;
-  rtx src_addr;
-  HOST_WIDE_INT i = 1, base = 0;
-  HOST_WIDE_INT offset = 0;
-  rtx elt;
-  bool addr_reg_loaded = false;
-  bool update = false;
-
-  if (count <= 1
-      || GET_CODE (XVECEXP (op, 0, 0)) != SET
-      || !REG_P (SET_DEST (XVECEXP (op, 0, 0))))
-    return false;
-
-  /* Check to see if this might be a write-back.  */
-  if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
-    {
-      i++;
-      base = 1;
-      update = true;
-
-      /* Now check it more carefully.  */
-      if (GET_CODE (SET_DEST (elt)) != REG
-          || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
-          || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
-          || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
-        return false;
-    }
-
-  /* Perform a quick check so we don't blow up below.  */
-  if (count <= i
-      || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
-      || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
-      || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
-    return false;
-
-  dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
-  src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
-  if (GET_CODE (src_addr) == PLUS)
-    {
-      if (GET_CODE (XEXP (src_addr, 1)) != CONST_INT)
-	return false;
-      offset = INTVAL (XEXP (src_addr, 1));
-      src_addr = XEXP (src_addr, 0);
-    }
-  if (!REG_P (src_addr))
-    return false;
-
-  for (; i < count; i++)
-    {
-      elt = XVECEXP (op, 0, i);
-
-      if (GET_CODE (elt) != SET
-          || GET_CODE (SET_DEST (elt)) != REG
-          || GET_MODE (SET_DEST (elt)) != SImode
-          || REGNO (SET_DEST (elt)) <= dest_regno
-          || GET_CODE (SET_SRC (elt)) != MEM
-          || GET_MODE (SET_SRC (elt)) != SImode
-          || ((GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
-	       || !rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
-	       || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
-	       || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != offset + (i - base) * 4)
-	      && (!REG_P (XEXP (SET_SRC (elt), 0))
-		  || offset + (i - base) * 4 != 0)))
-        return false;
-      dest_regno = REGNO (SET_DEST (elt));
-      if (dest_regno == REGNO (src_addr))
-        addr_reg_loaded = true;
-    }
-  /* For Thumb, we only have updating instructions.  If the pattern does
-     not describe an update, it must be because the address register is
-     in the list of loaded registers - on the hardware, this has the effect
-     of overriding the update.  */
-  if (update && addr_reg_loaded)
-    return false;
-  if (TARGET_THUMB1)
-    return update || addr_reg_loaded;
-  return true;
+ return ldm_stm_operation_p (op, /*load=*/true, SImode,
+                                 /*consecutive=*/false,
+                                 /*return_pc=*/false);
 })
 
 (define_special_predicate "store_multiple_operation"
   (match_code "parallel")
 {
-  HOST_WIDE_INT count = XVECLEN (op, 0);
-  unsigned src_regno;
-  rtx dest_addr;
-  HOST_WIDE_INT i = 1, base = 0, offset = 0;
-  rtx elt;
-
-  if (count <= 1
-      || GET_CODE (XVECEXP (op, 0, 0)) != SET)
-    return false;
-
-  /* Check to see if this might be a write-back.  */
-  if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
-    {
-      i++;
-      base = 1;
-
-      /* Now check it more carefully.  */
-      if (GET_CODE (SET_DEST (elt)) != REG
-          || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
-          || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
-          || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
-        return false;
-    }
-
-  /* Perform a quick check so we don't blow up below.  */
-  if (count <= i
-      || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
-      || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
-      || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
-    return false;
+ return ldm_stm_operation_p (op, /*load=*/false, SImode,
+                                 /*consecutive=*/false,
+                                 /*return_pc=*/false);
+})
 
-  src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
-  dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
-
-  if (GET_CODE (dest_addr) == PLUS)
-    {
-      if (GET_CODE (XEXP (dest_addr, 1)) != CONST_INT)
-	return false;
-      offset = INTVAL (XEXP (dest_addr, 1));
-      dest_addr = XEXP (dest_addr, 0);
-    }
-  if (!REG_P (dest_addr))
-    return false;
-
-  for (; i < count; i++)
-    {
-      elt = XVECEXP (op, 0, i);
+(define_special_predicate "pop_multiple_return"
+  (match_code "parallel")
+{
+ return ldm_stm_operation_p (op, /*load=*/true, SImode,
+                                 /*consecutive=*/false,
+                                 /*return_pc=*/true);
+})
 
-      if (GET_CODE (elt) != SET
-          || GET_CODE (SET_SRC (elt)) != REG
-          || GET_MODE (SET_SRC (elt)) != SImode
-          || REGNO (SET_SRC (elt)) <= src_regno
-          || GET_CODE (SET_DEST (elt)) != MEM
-          || GET_MODE (SET_DEST (elt)) != SImode
-          || ((GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
-	       || !rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
-	       || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
-               || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != offset + (i - base) * 4)
-	      && (!REG_P (XEXP (SET_DEST (elt), 0))
-		  || offset + (i - base) * 4 != 0)))
-        return false;
-      src_regno = REGNO (SET_SRC (elt));
-    }
-
-  return true;
+(define_special_predicate "pop_multiple_fp"
+  (match_code "parallel")
+{
+ return ldm_stm_operation_p (op, /*load=*/true, DFmode,
+                                 /*consecutive=*/true,
+                                 /*return_pc=*/false);
 })
 
 (define_special_predicate "multi_register_push"
@@ -508,6 +499,34 @@
   return true;
 })
 
+(define_predicate "push_mult_memory_operand"
+  (match_code "mem")
+{
+  /* ??? Given how PUSH_MULT is generated in the prologues, is there
+     any point in testing for thumb1 specially?  All of the variants
+     use the same form.  */
+  if (TARGET_THUMB1)
+    {
+      /* ??? No attempt is made to represent STMIA, or validate that
+	 the stack adjustment matches the register count.  This is
+	 true of the ARM/Thumb2 path as well.  */
+      rtx x = XEXP (op, 0);
+      if (GET_CODE (x) != PRE_MODIFY)
+	return false;
+      if (XEXP (x, 0) != stack_pointer_rtx)
+	return false;
+      x = XEXP (x, 1);
+      if (GET_CODE (x) != PLUS)
+	return false;
+      if (XEXP (x, 0) != stack_pointer_rtx)
+	return false;
+      return CONST_INT_P (XEXP (x, 1));
+    }
+
+  /* ARM and Thumb2 handle pre-modify in their legitimate_address.  */
+  return memory_operand (op, mode);
+})
+
 ;;-------------------------------------------------------------------------
 ;;
 ;; Thumb predicates
@@ -517,7 +536,7 @@
   (ior (and (match_code "reg,subreg")
 	    (match_operand 0 "s_register_operand"))
        (and (match_code "const_int")
-	    (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 256"))))
+	    (match_test "(UINTVAL (op)) < 256"))))
 
 (define_predicate "thumb1_cmpneg_operand"
   (and (match_code "const_int")
@@ -540,35 +559,12 @@
 
 ;;-------------------------------------------------------------------------
 ;;
-;; MAVERICK predicates
+;; iWMMXt predicates
 ;;
 
-(define_predicate "cirrus_register_operand"
-  (match_code "reg,subreg")
-{
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-
-  return (GET_CODE (op) == REG
-	  && (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
-	      || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
-})
-
-(define_predicate "cirrus_fp_register"
-  (match_code "reg,subreg")
-{
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-
-  return (GET_CODE (op) == REG
-	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER
-	      || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
-})
-
-(define_predicate "cirrus_shift_const"
-  (and (match_code "const_int")
-       (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 64")))
-
+(define_predicate "imm_or_reg_operand"
+  (ior (match_operand 0 "immediate_operand")
+       (match_operand 0 "register_operand")))
 
 ;; Neon predicates
 
@@ -580,45 +576,36 @@
 })
 
 (define_predicate "imm_for_neon_mov_operand"
-  (match_code "const_vector")
+  (match_code "const_vector,const_int")
 {
   return neon_immediate_valid_for_move (op, mode, NULL, NULL);
 })
 
-(define_predicate "imm_for_neon_logic_operand"
+(define_predicate "imm_for_neon_lshift_operand"
   (match_code "const_vector")
 {
-  return (TARGET_NEON
-          && neon_immediate_valid_for_logic (op, mode, 0, NULL, NULL));
+  return neon_immediate_valid_for_shift (op, mode, NULL, NULL, true);
 })
 
-(define_predicate "imm_for_neon_inv_logic_operand"
+(define_predicate "imm_for_neon_rshift_operand"
   (match_code "const_vector")
 {
-  return (TARGET_NEON
-          && neon_immediate_valid_for_logic (op, mode, 1, NULL, NULL));
+  return neon_immediate_valid_for_shift (op, mode, NULL, NULL, false);
 })
 
-(define_predicate "neon_logic_op2"
-  (ior (match_operand 0 "imm_for_neon_logic_operand")
-       (match_operand 0 "s_register_operand")))
+(define_predicate "imm_lshift_or_reg_neon"
+  (ior (match_operand 0 "s_register_operand")
+       (match_operand 0 "imm_for_neon_lshift_operand")))
 
-(define_predicate "neon_inv_logic_op2"
-  (ior (match_operand 0 "imm_for_neon_inv_logic_operand")
-       (match_operand 0 "s_register_operand")))
+(define_predicate "imm_rshift_or_reg_neon"
+  (ior (match_operand 0 "s_register_operand")
+       (match_operand 0 "imm_for_neon_rshift_operand")))
 
-;; TODO: We could check lane numbers more precisely based on the mode.
-(define_predicate "neon_lane_number"
-  (and (match_code "const_int")
-       (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
 ;; Predicates for named expanders that overlap multiple ISAs.
 
 (define_predicate "cmpdi_operand"
-  (if_then_else (match_test "TARGET_HARD_FLOAT && TARGET_MAVERICK")
-		(and (match_test "TARGET_ARM")
-		     (match_operand 0 "cirrus_fp_register"))
-		(and (match_test "TARGET_32BIT")
-		     (match_operand 0 "arm_di_operand"))))
+  (and (match_test "TARGET_32BIT")
+       (match_operand 0 "arm_di_operand")))
 
 ;; True if the operand is memory reference suitable for a ldrex/strex.
 (define_predicate "arm_sync_memory_operand"
@@ -629,57 +616,45 @@
 (define_special_predicate "vect_par_constant_high" 
   (match_code "parallel")
 {
-  HOST_WIDE_INT count = XVECLEN (op, 0);
-  int i;
-  int base = GET_MODE_NUNITS (mode);
-
-  if ((count < 1)
-      || (count != base/2))
-    return false;
-    
-  if (!VECTOR_MODE_P (mode))
-    return false;
-
-  for (i = 0; i < count; i++)
-   {
-     rtx elt = XVECEXP (op, 0, i);
-     int val;
-
-     if (GET_CODE (elt) != CONST_INT)
-       return false;
-
-     val = INTVAL (elt);
-     if (val != (base/2) + i)
-       return false;
-   }
-  return true; 
+  return arm_simd_check_vect_par_cnst_half_p (op, mode, true);
 })
 
 (define_special_predicate "vect_par_constant_low"
   (match_code "parallel")
 {
-  HOST_WIDE_INT count = XVECLEN (op, 0);
-  int i;
-  int base = GET_MODE_NUNITS (mode);
+  return arm_simd_check_vect_par_cnst_half_p (op, mode, false);
+})
+
+(define_predicate "const_double_vcvt_power_of_two_reciprocal"
+  (and (match_code "const_double")
+       (match_test "TARGET_32BIT
+		    && vfp3_const_double_for_fract_bits (op)")))
 
-  if ((count < 1)
-      || (count != base/2))
-    return false;
-    
-  if (!VECTOR_MODE_P (mode))
-    return false;
+(define_predicate "const_double_vcvt_power_of_two"
+  (and (match_code "const_double")
+       (match_test "TARGET_32BIT
+		    && vfp3_const_double_for_bits (op) > 0")))
+
+(define_predicate "neon_struct_operand"
+  (and (match_code "mem")
+       (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 2, true)")))
 
-  for (i = 0; i < count; i++)
-   {
-     rtx elt = XVECEXP (op, 0, i);
-     int val;
+(define_predicate "neon_permissive_struct_operand"
+  (and (match_code "mem")
+       (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 2, false)")))
+
+(define_predicate "neon_perm_struct_or_reg_operand"
+  (ior (match_operand 0 "neon_permissive_struct_operand")
+       (match_operand 0 "s_register_operand")))
 
-     if (GET_CODE (elt) != CONST_INT)
-       return false;
+(define_special_predicate "add_operator"
+  (match_code "plus"))
 
-     val = INTVAL (elt);
-     if (val != i)
-       return false;
-   } 
-  return true; 
-})
+(define_predicate "mem_noofs_operand"
+  (and (match_code "mem")
+       (match_code "reg" "0")))
+
+(define_predicate "call_insn_operand"
+  (ior (and (match_code "symbol_ref")
+	    (match_test "!arm_is_long_call_p (SYMBOL_REF_DECL (op))"))
+       (match_operand 0 "s_register_operand")))