From patchwork Mon Aug 2 20:38:32 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 60666 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 03990B70B4 for ; Tue, 3 Aug 2010 06:38:54 +1000 (EST) Received: (qmail 1156 invoked by alias); 2 Aug 2010 20:38:53 -0000 Received: (qmail 1134 invoked by uid 22791); 2 Aug 2010 20:38:49 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 02 Aug 2010 20:38:42 +0000 Received: (qmail 8433 invoked from network); 2 Aug 2010 20:38:40 -0000 Received: from unknown (HELO ?84.152.249.133?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 2 Aug 2010 20:38:40 -0000 Message-ID: <4C572CC8.3050006@codesourcery.com> Date: Mon, 02 Aug 2010 22:38:32 +0200 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.7) Gecko/20100724 Thunderbird/3.1.1 MIME-Version: 1.0 To: Richard Earnshaw CC: GCC Patches Subject: Re: More ARM pattern merging References: <4C56A025.9090304@codesourcery.com> <1280746294.20832.7.camel@e102346-lin.cambridge.arm.com> <4C56A3F5.7090706@codesourcery.com> <1280746578.20832.9.camel@e102346-lin.cambridge.arm.com> In-Reply-To: <1280746578.20832.9.camel@e102346-lin.cambridge.arm.com> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org On 08/02/2010 12:56 PM, Richard Earnshaw wrote: > I think merging is a good thing provided it doesn't degrade code > generation when the variant is unavailable. I see no reason why it should. I did run before-after comparisons, where, other than the mla thing, I only spotted some examples of better code generation which I'd previously not investigated: This is dealt with by the combiner patch I just submitted. New patch below, also includes the iorsi fixes; only lightly tested so far. Bernd * config/arm/thumb2.md (thumb2_notsi_shiftsi, thumbsi_notsi_shiftsi_compare0, thumb2_not_shiftsi_compare0_scratch, thumb2_cmpsi_shiftsi, thumb2_cmpsi_shiftsi_swp, thumb2_arith_shiftsi, thumb2_arith_shiftsi splitter, thumb2_arith_shiftsi_compare0, thumb2_arith_shiftsi_compare0_scratch, thumb2_sub_shiftsi, thumb2_sub_shiftsi_compare0, thumb2_sub_shiftsi_compare0_scratch, thumb2_iorsi3): Delete. (orsi_notsi_si): No longer a named pattern. (orsi_not_shiftsi_si): Renamed from thumb_orsi_not_shiftsi_si. * config/arm/predicates.md (shift_amount_operand): New. (mult_operator): New. * config/arm/arm.md (attr arch, attr arch_enabled, attr insn_enabled, attr enabled): New. (iorsi3_insn): Renamed from arm_iorsi3. Handle a new alternative if arch matches t2. (not_shiftsi): Renamed from arm_notsi_shiftsi. Handle Thumb2 variant. (not_shiftsi_compare0): Likewise, renamed from arm_notsi_shiftsi_compare0. (not_shiftsi_compare0_scratch): Likweise, renamed from arm_notsi_shiftsi_compare0_scratch. (cmpsi_shiftsi): Likewise, renamed from arm_cmpsi_shiftsi. (cmpsi_shiftsi_swp): Likewise, renamed from arm_cmpsi_shiftsi_swp. (arith_shiftsi): Handle Thumb2 variant. Set insn_enabled attribute so that the register alternative is disabled when the shift_operator is MULT. Use "M" as the constraint for constants. (arith_shiftsi splitter): Enable for TARGET_32BIT. (arith_shiftsi_compare0): Handle Thumb2 variant. Use "M" as the constraint for constants. (arith_shiftsi_compare0_scratch): Likewise. (sub_shiftsi, sub_shiftsi_compare0, sub_shiftsi_compare0_scratch): Handle Thumb2 alternative. Index: config/arm/thumb2.md =================================================================== --- config/arm/thumb2.md.orig +++ config/arm/thumb2.md @@ -120,47 +120,6 @@ (set_attr "length" "10,10,14")] ) -(define_insn "*thumb2_notsi_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "M")])))] - "TARGET_THUMB2" - "mvn%?\\t%0, %1%S3" - [(set_attr "predicable" "yes") - (set_attr "shift" "1") - (set_attr "type" "alu_shift")] -) - -(define_insn "*thumb2_notsi_shiftsi_compare0" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "M")])) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] - "TARGET_THUMB2" - "mvn%.\\t%0, %1%S3" - [(set_attr "conds" "set") - (set_attr "shift" "1") - (set_attr "type" "alu_shift")] -) - -(define_insn "*thumb2_not_shiftsi_compare0_scratch" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "M")])) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_THUMB2" - "mvn%.\\t%0, %1%S3" - [(set_attr "conds" "set") - (set_attr "shift" "1") - (set_attr "type" "alu_shift")] -) - ;; Thumb-2 does not have rsc, so use a clever trick with shifter operands. (define_insn "*thumb2_negdi2" [(set (match_operand:DI 0 "s_register_operand" "=&r,r") @@ -260,32 +219,6 @@ (set_attr "neg_pool_range" "*,*,*,250")] ) -(define_insn "*thumb2_cmpsi_shiftsi" - [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 0 "s_register_operand" "r") - (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "M")])))] - "TARGET_THUMB2" - "cmp%?\\t%0, %1%S3" - [(set_attr "conds" "set") - (set_attr "shift" "1") - (set_attr "type" "alu_shift")] -) - -(define_insn "*thumb2_cmpsi_shiftsi_swp" - [(set (reg:CC_SWP CC_REGNUM) - (compare:CC_SWP (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "const_int_operand" "M")]) - (match_operand:SI 0 "s_register_operand" "r")))] - "TARGET_THUMB2" - "cmp%?\\t%0, %1%S3" - [(set_attr "conds" "set") - (set_attr "shift" "1") - (set_attr "type" "alu_shift")] -) - (define_insn "*thumb2_cmpsi_neg_shiftsi" [(set (reg:CC CC_REGNUM) (compare:CC (match_operand:SI 0 "s_register_operand" "r") @@ -396,122 +329,6 @@ ;; addresses will have the thumb bit set correctly. -;; Patterns to allow combination of arithmetic, cond code and shifts - -(define_insn "*thumb2_arith_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "const_int_operand" "M")]) - (match_operand:SI 2 "s_register_operand" "rk")]))] - "TARGET_THUMB2" - "%i1%?\\t%0, %2, %4%S3" - [(set_attr "predicable" "yes") - (set_attr "shift" "4") - (set_attr "type" "alu_shift")] -) - -;; ??? What does this splitter do? Copied from the ARM version -(define_split - [(set (match_operand:SI 0 "s_register_operand" "") - (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 2 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "") - (match_operand:SI 5 "const_int_operand" "")]) - (match_operand:SI 6 "s_register_operand" "")]) - (match_operand:SI 7 "arm_rhs_operand" "")])) - (clobber (match_operand:SI 8 "s_register_operand" ""))] - "TARGET_32BIT" - [(set (match_dup 8) - (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) - (match_dup 6)])) - (set (match_dup 0) - (match_op_dup 1 [(match_dup 8) (match_dup 7)]))] - "") - -(define_insn "*thumb2_arith_shiftsi_compare0" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "const_int_operand" "M")]) - (match_operand:SI 2 "s_register_operand" "r")]) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) - (match_dup 2)]))] - "TARGET_32BIT" - "%i1%.\\t%0, %2, %4%S3" - [(set_attr "conds" "set") - (set_attr "shift" "4") - (set_attr "type" "alu_shift")] -) - -(define_insn "*thumb2_arith_shiftsi_compare0_scratch" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "const_int_operand" "M")]) - (match_operand:SI 2 "s_register_operand" "r")]) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_THUMB2" - "%i1%.\\t%0, %2, %4%S3" - [(set_attr "conds" "set") - (set_attr "shift" "4") - (set_attr "type" "alu_shift")] -) - -(define_insn "*thumb2_sub_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_int_operand" "M")])))] - "TARGET_THUMB2" - "sub%?\\t%0, %1, %3%S2" - [(set_attr "predicable" "yes") - (set_attr "shift" "3") - (set_attr "type" "alu_shift")] -) - -(define_insn "*thumb2_sub_shiftsi_compare0" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_int_operand" "M")])) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "TARGET_THUMB2" - "sub%.\\t%0, %1, %3%S2" - [(set_attr "conds" "set") - (set_attr "shift" "3") - (set_attr "type" "alu_shift")] -) - -(define_insn "*thumb2_sub_shiftsi_compare0_scratch" - [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV - (minus:SI (match_operand:SI 1 "s_register_operand" "r") - (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "const_int_operand" "M")])) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_THUMB2" - "sub%.\\t%0, %1, %3%S2" - [(set_attr "conds" "set") - (set_attr "shift" "3") - (set_attr "type" "alu_shift")] -) - (define_insn "*thumb2_and_scc" [(set (match_operand:SI 0 "s_register_operand" "=r") (and:SI (match_operator:SI 1 "arm_comparison_operator" @@ -1365,7 +1182,7 @@ (set_attr "length" "2")] ) -(define_insn "orsi_notsi_si" +(define_insn "*orsi_notsi_si" [(set (match_operand:SI 0 "s_register_operand" "=r") (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r")) (match_operand:SI 1 "s_register_operand" "r")))] @@ -1374,7 +1191,7 @@ [(set_attr "predicable" "yes")] ) -(define_insn "*thumb_orsi_not_shiftsi_si" +(define_insn "*orsi_not_shiftsi_si" [(set (match_operand:SI 0 "s_register_operand" "=r") (ior:SI (not:SI (match_operator:SI 4 "shift_operator" [(match_operand:SI 2 "s_register_operand" "r") @@ -1387,29 +1204,6 @@ (set_attr "type" "alu_shift")] ) -(define_insn_and_split "*thumb2_iorsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") - (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,r") - (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] - "TARGET_THUMB2" - "@ - orr%?\\t%0, %1, %2 - orn%?\\t%0, %1, #%B2 - #" - "TARGET_THUMB2 - && GET_CODE (operands[2]) == CONST_INT - && !(const_ok_for_arm (INTVAL (operands[2])) - || const_ok_for_arm (~INTVAL (operands[2])))" - [(clobber (const_int 0))] - " - arm_split_constant (IOR, SImode, curr_insn, - INTVAL (operands[2]), operands[0], operands[1], 0); - DONE; - " - [(set_attr "length" "4,4,16") - (set_attr "predicable" "yes")] -) - (define_peephole2 [(set (match_operand:CC_NOOV 0 "cc_register" "") (compare:CC_NOOV (zero_extract:SI Index: config/arm/predicates.md =================================================================== --- config/arm/predicates.md.orig +++ config/arm/predicates.md @@ -128,6 +128,11 @@ (ior (match_operand 0 "arm_rhs_operand") (match_operand 0 "memory_operand"))) +(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 "arm_add_operand" (ior (match_operand 0 "arm_rhs_operand") (match_operand 0 "arm_neg_immediate_operand"))) @@ -221,6 +226,10 @@ (match_code "ashift,ashiftrt,lshiftrt,rotatert")) (match_test "mode == GET_MODE (op)"))) +;; True for MULT, to identify which variant of shift_operator is in use. +(define_special_predicate "mult_operator" + (match_code "mult")) + ;; True for operators that have 16-bit thumb variants. */ (define_special_predicate "thumb_16bit_operator" (match_code "plus,minus,and,ior,xor")) Index: config/arm/arm.md =================================================================== --- config/arm/arm.md.orig +++ config/arm/arm.md @@ -167,6 +167,59 @@ ; LENGTH of an instruction (in bytes) (define_attr "length" "" (const_int 4)) +; The architecture which supports the instruction (or alternative). +; This can be "a" for ARM, "t" for either of the Thumbs, "32" for +; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6" +; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without +; arm_arch6. This attribute is used to compute attribute "enabled", +; use type "any" to enable an alternative in all cases. +(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6" + (const_string "any")) + +(define_attr "arch_enabled" "no,yes" + (cond [(eq_attr "arch" "any") + (const_string "yes") + + (and (eq_attr "arch" "a") + (ne (symbol_ref "TARGET_ARM") (const_int 0))) + (const_string "yes") + + (and (eq_attr "arch" "t") + (ne (symbol_ref "TARGET_THUMB") (const_int 0))) + (const_string "yes") + + (and (eq_attr "arch" "t1") + (ne (symbol_ref "TARGET_THUMB1") (const_int 0))) + (const_string "yes") + + (and (eq_attr "arch" "t2") + (ne (symbol_ref "TARGET_THUMB2") (const_int 0))) + (const_string "yes") + + (and (eq_attr "arch" "32") + (ne (symbol_ref "TARGET_32BIT") (const_int 0))) + (const_string "yes") + + (and (eq_attr "arch" "v6") + (ne (symbol_ref "(TARGET_32BIT && arm_arch6)") (const_int 0))) + (const_string "yes") + + (and (eq_attr "arch" "nov6") + (ne (symbol_ref "(TARGET_32BIT && !arm_arch6)") (const_int 0))) + (const_string "yes")] + (const_string "no"))) + +; Allows an insn to disable certain alternatives for reasons other than +; arch support. +(define_attr "insn_enabled" "no,yes" + (const_string "yes")) + +; Enable all alternatives that are both arch_enabled and insn_enabled. +(define_attr "enabled" "no,yes" + (if_then_else (eq_attr "insn_enabled" "yes") + (attr "arch_enabled") + (const_string "no"))) + ; POOL_RANGE is how far away from a constant pool entry that this insn ; can be placed. If the distance is zero, then this insn will never ; reference the pool. @@ -2699,26 +2752,28 @@ " ) -(define_insn_and_split "*arm_iorsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (ior:SI (match_operand:SI 1 "s_register_operand" "r,r") - (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))] - "TARGET_ARM" +(define_insn_and_split "*iorsi3_insn" + [(set (match_operand:SI 0 "s_register_operand" "=r,r,r") + (ior:SI (match_operand:SI 1 "s_register_operand" "%r,r,r") + (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))] + "TARGET_32BIT" "@ orr%?\\t%0, %1, %2 + orn%?\\t%0, %1, #%B2 #" - "TARGET_ARM + "TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT - && !const_ok_for_arm (INTVAL (operands[2]))" + && !(const_ok_for_arm (INTVAL (operands[2])) + || (TARGET_THUMB2 && const_ok_for_arm (~INTVAL (operands[2]))))" [(clobber (const_int 0))] - " +{ arm_split_constant (IOR, SImode, curr_insn, INTVAL (operands[2]), operands[0], operands[1], 0); DONE; - " - [(set_attr "length" "4,16") - (set_attr "predicable" "yes")] -) +} + [(set_attr "length" "4,4,16") + (set_attr "arch" "32,t2,32") + (set_attr "predicable" "yes")]) (define_insn "*thumb1_iorsi3_insn" [(set (match_operand:SI 0 "register_operand" "=l") @@ -3486,52 +3541,48 @@ (set_attr "shift" "1")] ) -(define_insn "*arm_notsi_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") +(define_insn "*not_shiftsi" + [(set (match_operand:SI 0 "s_register_operand" "=r,r") (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])))] - "TARGET_ARM" + [(match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "shift_amount_operand" "M,rM")])))] + "TARGET_32BIT" "mvn%?\\t%0, %1%S3" [(set_attr "predicable" "yes") (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) -(define_insn "*arm_notsi_shiftsi_compare0" +(define_insn "*not_shiftsi_compare0" [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") + (compare:CC_NOOV + (not:SI (match_operator:SI 3 "shift_operator" + [(match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "shift_amount_operand" "M,rM")])) + (const_int 0))) + (set (match_operand:SI 0 "s_register_operand" "=r,r") (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))] - "TARGET_ARM" + "TARGET_32BIT" "mvn%.\\t%0, %1%S3" [(set_attr "conds" "set") (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) -(define_insn "*arm_not_shiftsi_compare0_scratch" +(define_insn "*not_shiftsi_compare0_scratch" [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_ARM" + (compare:CC_NOOV + (not:SI (match_operator:SI 3 "shift_operator" + [(match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "shift_amount_operand" "M,rM")])) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r,r"))] + "TARGET_32BIT" "mvn%.\\t%0, %1%S3" [(set_attr "conds" "set") (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) ;; We don't really have extzv, but defining this using shifts helps ;; to reduce register pressure later on. @@ -7028,35 +7079,31 @@ [(set_attr "conds" "set")] ) -(define_insn "*arm_cmpsi_shiftsi" +(define_insn "*cmpsi_shiftsi" [(set (reg:CC CC_REGNUM) - (compare:CC (match_operand:SI 0 "s_register_operand" "r") + (compare:CC (match_operand:SI 0 "s_register_operand" "r,r") (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "arm_rhs_operand" "rM")])))] - "TARGET_ARM" + [(match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "shift_amount_operand" "M,rM")])))] + "TARGET_32BIT" "cmp%?\\t%0, %1%S3" [(set_attr "conds" "set") (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) -(define_insn "*arm_cmpsi_shiftsi_swp" +(define_insn "*cmpsi_shiftsi_swp" [(set (reg:CC_SWP CC_REGNUM) (compare:CC_SWP (match_operator:SI 3 "shift_operator" - [(match_operand:SI 1 "s_register_operand" "r") - (match_operand:SI 2 "reg_or_int_operand" "rM")]) - (match_operand:SI 0 "s_register_operand" "r")))] - "TARGET_ARM" + [(match_operand:SI 1 "s_register_operand" "r,r") + (match_operand:SI 2 "shift_amount_operand" "M,rM")]) + (match_operand:SI 0 "s_register_operand" "r,r")))] + "TARGET_32BIT" "cmp%?\\t%0, %1%S3" [(set_attr "conds" "set") (set_attr "shift" "1") - (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) (define_insn "*arm_cmpsi_negshiftsi_si" [(set (reg:CC_Z CC_REGNUM) @@ -8408,20 +8455,28 @@ ;; Patterns to allow combination of arithmetic, cond code and shifts (define_insn "*arith_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") + [(set (match_operand:SI 0 "s_register_operand" "=r,r") (match_operator:SI 1 "shiftable_operator" [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "reg_or_int_operand" "rI")]) - (match_operand:SI 2 "s_register_operand" "rk")]))] - "TARGET_ARM" + [(match_operand:SI 4 "s_register_operand" "r,r") + (match_operand:SI 5 "shift_amount_operand" "M,r")]) + (match_operand:SI 2 "s_register_operand" "rk,rk")]))] + "TARGET_32BIT" "%i1%?\\t%0, %2, %4%S3" [(set_attr "predicable" "yes") (set_attr "shift" "4") - (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + ;; We have to make sure to disable the second alternative if + ;; the shift_operator is MULT, since otherwise the insn will + ;; also match a multiply_accumulate pattern and validate_change + ;; will allow a replacement of the constant with a register + ;; despite the checks done in shift_operator. + (set_attr_alternative "insn_enabled" + [(const_string "yes") + (if_then_else + (match_operand:SI 3 "mult_operator" "") + (const_string "no") (const_string "yes"))]) + (set_attr "type" "alu_shift,alu_shift_reg")]) (define_split [(set (match_operand:SI 0 "s_register_operand" "") @@ -8433,7 +8488,7 @@ (match_operand:SI 6 "s_register_operand" "")]) (match_operand:SI 7 "arm_rhs_operand" "")])) (clobber (match_operand:SI 8 "s_register_operand" ""))] - "TARGET_ARM" + "TARGET_32BIT" [(set (match_dup 8) (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) (match_dup 6)])) @@ -8443,95 +8498,86 @@ (define_insn "*arith_shiftsi_compare0" [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "reg_or_int_operand" "rI")]) - (match_operand:SI 2 "s_register_operand" "r")]) - (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") + (compare:CC_NOOV + (match_operator:SI 1 "shiftable_operator" + [(match_operator:SI 3 "shift_operator" + [(match_operand:SI 4 "s_register_operand" "r,r") + (match_operand:SI 5 "shift_amount_operand" "M,r")]) + (match_operand:SI 2 "s_register_operand" "r,r")]) + (const_int 0))) + (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)]) (match_dup 2)]))] - "TARGET_ARM" + "TARGET_32BIT" "%i1%.\\t%0, %2, %4%S3" [(set_attr "conds" "set") (set_attr "shift" "4") - (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) (define_insn "*arith_shiftsi_compare0_scratch" [(set (reg:CC_NOOV CC_REGNUM) - (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator" - [(match_operator:SI 3 "shift_operator" - [(match_operand:SI 4 "s_register_operand" "r") - (match_operand:SI 5 "reg_or_int_operand" "rI")]) - (match_operand:SI 2 "s_register_operand" "r")]) - (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_ARM" + (compare:CC_NOOV + (match_operator:SI 1 "shiftable_operator" + [(match_operator:SI 3 "shift_operator" + [(match_operand:SI 4 "s_register_operand" "r,r") + (match_operand:SI 5 "shift_amount_operand" "M,r")]) + (match_operand:SI 2 "s_register_operand" "r,r")]) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r,r"))] + "TARGET_32BIT" "%i1%.\\t%0, %2, %4%S3" [(set_attr "conds" "set") (set_attr "shift" "4") - (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) (define_insn "*sub_shiftsi" - [(set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_operand:SI 1 "s_register_operand" "r") + [(set (match_operand:SI 0 "s_register_operand" "=r,r") + (minus:SI (match_operand:SI 1 "s_register_operand" "r,r") (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])))] - "TARGET_ARM" + [(match_operand:SI 3 "s_register_operand" "r,r") + (match_operand:SI 4 "shift_amount_operand" "M,r")])))] + "TARGET_32BIT" "sub%?\\t%0, %1, %3%S2" [(set_attr "predicable" "yes") (set_attr "shift" "3") - (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) (define_insn "*sub_shiftsi_compare0" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV - (minus:SI (match_operand:SI 1 "s_register_operand" "r") + (minus:SI (match_operand:SI 1 "s_register_operand" "r,r") (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])) + [(match_operand:SI 3 "s_register_operand" "r,r") + (match_operand:SI 4 "shift_amount_operand" "M,rM")])) (const_int 0))) - (set (match_operand:SI 0 "s_register_operand" "=r") - (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3) - (match_dup 4)])))] - "TARGET_ARM" + (set (match_operand:SI 0 "s_register_operand" "=r,r") + (minus:SI (match_dup 1) + (match_op_dup 2 [(match_dup 3) (match_dup 4)])))] + "TARGET_32BIT" "sub%.\\t%0, %1, %3%S2" [(set_attr "conds" "set") (set_attr "shift" "3") - (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) (define_insn "*sub_shiftsi_compare0_scratch" [(set (reg:CC_NOOV CC_REGNUM) (compare:CC_NOOV - (minus:SI (match_operand:SI 1 "s_register_operand" "r") + (minus:SI (match_operand:SI 1 "s_register_operand" "r,r") (match_operator:SI 2 "shift_operator" - [(match_operand:SI 3 "s_register_operand" "r") - (match_operand:SI 4 "reg_or_int_operand" "rM")])) + [(match_operand:SI 3 "s_register_operand" "r,r") + (match_operand:SI 4 "shift_amount_operand" "M,rM")])) (const_int 0))) - (clobber (match_scratch:SI 0 "=r"))] - "TARGET_ARM" + (clobber (match_scratch:SI 0 "=r,r"))] + "TARGET_32BIT" "sub%.\\t%0, %1, %3%S2" [(set_attr "conds" "set") (set_attr "shift" "3") - (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "") - (const_string "alu_shift") - (const_string "alu_shift_reg")))] -) - + (set_attr "arch" "32,a") + (set_attr "type" "alu_shift,alu_shift_reg")]) (define_insn "*and_scc"