From patchwork Wed Apr 20 15:27:24 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Stubbs X-Patchwork-Id: 92224 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 936701007D9 for ; Thu, 21 Apr 2011 01:27:44 +1000 (EST) Received: (qmail 22461 invoked by alias); 20 Apr 2011 15:27:42 -0000 Received: (qmail 22451 invoked by uid 22791); 20 Apr 2011 15:27:41 -0000 X-SWARE-Spam-Status: No, hits=-1.7 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; Wed, 20 Apr 2011 15:27:27 +0000 Received: (qmail 5691 invoked from network); 20 Apr 2011 15:27:26 -0000 Received: from unknown (HELO ?192.168.0.104?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 20 Apr 2011 15:27:26 -0000 Message-ID: <4DAEFB5C.8020802@codesourcery.com> Date: Wed, 20 Apr 2011 16:27:24 +0100 From: Andrew Stubbs User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.14) Gecko/20110223 Lightning/1.0b2 Thunderbird/3.1.8 MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org CC: patches@linaro.org Subject: [PATCH][ARM] Add support for ADDW and SUBW instructions 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 patch adds basic support for the Thumb ADDW and SUBW instructions. The patch permits the compiler to use the new instructions for constants that can be loaded with a single instruction (i.e. 16-bit unshifted), but does not support use of addw with split-constants; I have a patch for that coming soon. This patch requires that my previously posted patch for MOVW is applied first. OK? Andrew 2011-04-20 Andrew Stubbs gcc/ * config/arm/arm-protos.h (const_ok_for_op): Add prototype. * config/arm/arm.c (const_ok_for_op): Add support for addw/subw. Remove prototype. Remove static function type. * config/arm/arm.md (*arm_addsi3): Add addw/subw support. Add arch attribute. (*arm_subsi3_insn): Add subw support. Add arch attribute. * config/arm/constraints.md (Pj, PJ): New constraints. --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -46,6 +46,7 @@ extern bool arm_vector_mode_supported_p (enum machine_mode); extern bool arm_small_register_classes_for_mode_p (enum machine_mode); extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode); extern int const_ok_for_arm (HOST_WIDE_INT); +extern int const_ok_for_op (HOST_WIDE_INT, enum rtx_code); extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx, HOST_WIDE_INT, rtx, rtx, int); extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *); --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -82,7 +82,6 @@ inline static int thumb1_index_register_rtx_p (rtx, int); static bool arm_legitimate_address_p (enum machine_mode, rtx, bool); static int thumb_far_jump_used_p (void); static bool thumb_force_lr_save (void); -static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code); static rtx emit_sfm (int, int); static unsigned arm_size_return_regs (void); static bool arm_assemble_integer (rtx, unsigned int, int); @@ -2453,7 +2452,7 @@ const_ok_for_arm (HOST_WIDE_INT i) } /* Return true if I is a valid constant for the operation CODE. */ -static int +int const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code) { if (const_ok_for_arm (i)) @@ -2469,6 +2468,13 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code) return 0; case PLUS: + /* See if we can use addw or subw. */ + if (TARGET_THUMB2 + && ((i & 0xfffff000) == 0 + || ((-i) & 0xfffff000) == 0)) + return 1; + /* else fall through. */ + case COMPARE: case EQ: case NE: --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -707,21 +707,24 @@ ;; (plus (reg rN) (reg sp)) into (reg rN). In this case reload will ;; put the duplicated register first, and not try the commutative version. (define_insn_and_split "*arm_addsi3" - [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k,r") - (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk") - (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))] + [(set (match_operand:SI 0 "s_register_operand" "=r, k,r,r, k, r, k,r, k, r") + (plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k, rk,k,rk,k, rk") + (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n")))] "TARGET_32BIT" "@ add%?\\t%0, %1, %2 add%?\\t%0, %1, %2 add%?\\t%0, %2, %1 + addw%?\\t%0, %1, %2 + addw%?\\t%0, %1, %2 sub%?\\t%0, %1, #%n2 sub%?\\t%0, %1, #%n2 + subw%?\\t%0, %1, #%n2 + subw%?\\t%0, %1, #%n2 #" "TARGET_32BIT && GET_CODE (operands[2]) == CONST_INT - && !(const_ok_for_arm (INTVAL (operands[2])) - || const_ok_for_arm (-INTVAL (operands[2]))) + && !const_ok_for_op (INTVAL (operands[2]), PLUS) && (reload_completed || !arm_eliminable_register (operands[1]))" [(clobber (const_int 0))] " @@ -730,8 +733,9 @@ operands[1], 0); DONE; " - [(set_attr "length" "4,4,4,4,4,16") - (set_attr "predicable" "yes")] + [(set_attr "length" "4,4,4,4,4,4,4,4,4,16") + (set_attr "predicable" "yes") + (set_attr "arch" "*,*,*,t2,t2,*,*,t2,t2,*")] ) (define_insn_and_split "*thumb1_addsi3" @@ -1184,28 +1188,33 @@ ; ??? Check Thumb-2 split length (define_insn_and_split "*arm_subsi3_insn" - [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r,r") - (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k,?n,r") - (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, r,?n")))] + [(set (match_operand:SI 0 "s_register_operand" "=r,r,rk,r, k, r,r") + (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,r,k, rk,k, ?n,r") + (match_operand:SI 2 "reg_or_int_operand" "r,rI,r, Pj,Pj,r,?n")))] "TARGET_32BIT" "@ rsb%?\\t%0, %2, %1 sub%?\\t%0, %1, %2 sub%?\\t%0, %1, %2 + subw%?\\t%0, %1, %2 + subw%?\\t%0, %1, %2 # #" "&& ((GET_CODE (operands[1]) == CONST_INT - && !const_ok_for_arm (INTVAL (operands[1]))) + && !(const_ok_for_arm (INTVAL (operands[1])) + || satisfies_constraint_Pj (operands[2]))) || (GET_CODE (operands[2]) == CONST_INT - && !const_ok_for_arm (INTVAL (operands[2]))))" + && !(const_ok_for_arm (INTVAL (operands[2])) + || satisfies_constraint_Pj (operands[2]))))" [(clobber (const_int 0))] " arm_split_constant (MINUS, SImode, curr_insn, INTVAL (operands[1]), operands[0], operands[2], 0); DONE; " - [(set_attr "length" "4,4,4,16,16") - (set_attr "predicable" "yes")] + [(set_attr "length" "4,4,4,4,4,16,16") + (set_attr "predicable" "yes") + (set_attr "arch" "*,*,*,t2,t2,*,*")] ) (define_peephole2 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -31,7 +31,7 @@ ;; The following multi-letter normal constraints have been used: ;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dz ;; in Thumb-1 state: Pa, Pb, Pc, Pd -;; in Thumb-2 state: Ps, Pt, Pu, Pv, Pw, Px, Py +;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py ;; The following memory constraints have been used: ;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us @@ -74,6 +74,18 @@ (and (match_code "const_int") (match_test "(ival & 0xffff0000) == 0"))))) +(define_constraint "Pj" + "A 12-bit constant suitable for an ADDW or SUBW instruction. (Thumb-2)" + (and (match_code "const_int") + (and (match_test "TARGET_THUMB2") + (match_test "(ival & 0xfffff000) == 0")))) + +(define_constraint "PJ" + "A constant that satisfies the Pj constrant if negated." + (and (match_code "const_int") + (and (match_test "TARGET_THUMB2") + (match_test "((-ival) & 0xfffff000) == 0")))) + (define_register_constraint "k" "STACK_REG" "@internal The stack register.")