From patchwork Mon Aug 2 10:38:29 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 60529 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 AD347B70CC for ; Mon, 2 Aug 2010 20:38:55 +1000 (EST) Received: (qmail 20119 invoked by alias); 2 Aug 2010 10:38:52 -0000 Received: (qmail 20100 invoked by uid 22791); 2 Aug 2010 10:38:48 -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 10:38:40 +0000 Received: (qmail 13645 invoked from network); 2 Aug 2010 10:38:37 -0000 Received: from unknown (HELO ?84.152.249.133?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 2 Aug 2010 10:38:37 -0000 Message-ID: <4C56A025.9090304@codesourcery.com> Date: Mon, 02 Aug 2010 12:38:29 +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: GCC Patches CC: Richard Earnshaw Subject: More ARM pattern merging 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 This deals with the various arith_shift patterns which are needlessly duplicated in thumb2.md. Merging them requires that we define attribute enabled, so we can conditionally enable the correct alternatives. There was a problem with reload_cse_regs. Since arith_shiftsi can take the same form as mulsi3_addsi, when reload_cse_regs tries to replace a constant operand with a register, arith_shiftsi no longer matches, but the mla does, so the replacement is validated. Effect of this patch: mov r2, #4 - mla r1, r5, r2, r0 + add r1, r0, r5, asl #2 Just guessing, but probably mla is a more expensive operation? Notes: - I left thumb2_cmpsi_neg_shiftsi alone for now, as it differs from the corresponding arm.md pattern - Some ARM patterns used rI for the shift amount, corrected to the M,r form now used elsewhere. Regression tested (a slightly earlier version with some different pattern names) with the usual set of flags on arm-linux. 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, orsi_notsi_si, thumb_orsi_not_shiftsi_si, thumb2_iorsi3): Delete. * 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. (orsi_notsi_si, orsi_not_shiftsi_si): New patterns. (iorsi3_insn): Renamed from arm_iorsi3. Handle a new alternative if arch matches v6. (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,51 +1182,6 @@ (set_attr "length" "2")] ) -(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")))] - "TARGET_THUMB2" - "orn%?\\t%0, %1, %2" - [(set_attr "predicable" "yes")] -) - -(define_insn "*thumb_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") - (match_operand:SI 3 "const_int_operand" "M")])) - (match_operand:SI 1 "s_register_operand" "r")))] - "TARGET_THUMB2" - "orn%?\\t%0, %1, %2%S4" - [(set_attr "predicable" "yes") - (set_attr "shift" "2") - (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,48 @@ " ) -(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 "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")))] + "TARGET_32BIT && arm_arch6" + "orn%?\\t%0, %1, %2" + [(set_attr "predicable" "yes")]) + +(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") + (match_operand:SI 3 "const_int_operand" "M")])) + (match_operand:SI 1 "s_register_operand" "r")))] + "TARGET_32BIT && arm_arch6" + "orn%?\\t%0, %1, %2%S4" + [(set_attr "predicable" "yes") + (set_attr "shift" "2") + (set_attr "type" "alu_shift")]) + +(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])) + || (arm_arch6 && 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,v6,32") + (set_attr "predicable" "yes")]) (define_insn "*thumb1_iorsi3_insn" [(set (match_operand:SI 0 "register_operand" "=l") @@ -3486,52 +3561,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. @@ -7005,35 +7076,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) @@ -8385,20 +8452,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" "") @@ -8410,7 +8485,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)])) @@ -8420,95 +8495,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" Index: postreload.c =================================================================== --- postreload.c.orig +++ postreload.c @@ -573,6 +573,7 @@ reload_cse_simplify_operands (rtx insn, alternative yet and the operand being replaced is not a cheap CONST_INT. */ if (op_alt_regno[i][j] == -1 + && recog_data.alternative_enabled_p[j] && reg_fits_class_p (testreg, rclass, 0, mode) && (!CONST_INT_P (recog_data.operand[i]) || (rtx_cost (recog_data.operand[i], SET,