Mercurial > hg > CbC > CbC_gcc
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")))