From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26770 invoked by alias); 18 Oct 2012 13:40:53 -0000 Received: (qmail 26746 invoked by uid 22791); 18 Oct 2012 13:40:51 -0000 X-SWARE-Spam-Status: No, hits=-1.6 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE X-Spam-Check-By: sourceware.org Received: from service87.mimecast.com (HELO service87.mimecast.com) (91.220.42.44) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 18 Oct 2012 13:40:44 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Thu, 18 Oct 2012 14:40:42 +0100 Received: from [10.1.69.67] ([10.1.255.212]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Thu, 18 Oct 2012 14:40:41 +0100 Message-ID: <508006D6.4090806@arm.com> Date: Thu, 18 Oct 2012 13:54:00 -0000 From: Richard Earnshaw User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:15.0) Gecko/20120907 Thunderbird/15.0.1 MIME-Version: 1.0 To: Greta Yorsh CC: GCC Patches , Ramana Radhakrishnan , "nickc@redhat.com" , "paul@codesourcery.com" Subject: Re: [PATCH, ARM][1/4] New RTL patterns for LDRD/STRD in Thumb mode References: <001601cda6f6$2b3fcea0$81bf6be0$@yorsh@arm.com> <001701cda6f8$5f19a9b0$1d4cfd10$@yorsh@arm.com> In-Reply-To: <001701cda6f8$5f19a9b0$1d4cfd10$@yorsh@arm.com> X-MC-Unique: 112101814404203401 Content-Type: text/plain; charset=WINDOWS-1252; format=flowed Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2012-10/txt/msg01711.txt.bz2 On 10/10/12 16:03, Greta Yorsh wrote: > This patch adds define_insn patterns for LDRD and STRD in Thumb mode. > > ChangeLog > > gcc/ > > 2012-09-13 Sameera Deshpande > Greta Yorsh > > * config/arm/arm-protos.h (offset_ok_for_ldrd_strd): New > declaration. > (operands_ok_ldrd_strd): Likewise. > * config/arm/arm.c (offset_ok_for_ldrd_strd): New function. > (operands_ok_ldrd_strd): Likewise. > * config/arm/arm.md (thumb2_ldrd, thumb2_ldrd_base): New pattern= s. > (thumb2_ldrd_base_neg): Likewise. > (thumb2_strd, thumb2_strd_base, thumb_strd_base_neg): Likewise. > * predicates.md (ldrd_strd_offset_operand): New predicate. > * config/arm/constraints.md (Dd): New constraint. > > > 1-thumb-patterns.patch.txt > > > diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h > index c590ef4..317bca7 100644 > --- a/gcc/config/arm/arm-protos.h > +++ b/gcc/config/arm/arm-protos.h > @@ -116,6 +116,8 @@ extern bool gen_stm_seq (rtx *, int); > extern bool gen_const_stm_seq (rtx *, int); > extern rtx arm_gen_load_multiple (int *, int, rtx, int, rtx, HOST_WIDE_= INT *); > extern rtx arm_gen_store_multiple (int *, int, rtx, int, rtx, HOST_WIDE= _INT *); > +extern bool offset_ok_for_ldrd_strd (HOST_WIDE_INT); > +extern bool operands_ok_ldrd_strd (rtx, rtx, rtx, HOST_WIDE_INT, bool, b= ool); > extern int arm_gen_movmemqi (rtx *); > extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx); > extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx, > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index 3fce8c4..b3a3774 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -12123,6 +12123,75 @@ arm_pad_reg_upward (enum machine_mode mode, > return !BYTES_BIG_ENDIAN; > } > > +/* Returns true iff OFFSET is valid for use in an LDRD/STRD instruction, > + assuming that the address in the base register is word aligned. */ > +bool > +offset_ok_for_ldrd_strd (HOST_WIDE_INT offset) > +{ > + HOST_WIDE_INT max_offset; > + > + /* Offset must be a multiple of 4 in Thumb mode. */ > + if (TARGET_THUMB2 && ((offset & 3) !=3D 0)) > + return false; > + > + if (TARGET_THUMB2) > + max_offset =3D 1020; > + else if (TARGET_ARM) > + max_offset =3D 255; > + else > + gcc_unreachable (); > + > + return ((offset <=3D max_offset) && (offset >=3D -max_offset)); > +} > + > +/* Checks whether the operands are valid for use in an LDRD/STRD instruc= tion. > + Assumes that RT, RT2, and RTN are REG. This is guaranteed by the pat= terns. > + Assumes that the address in the base register RTN is word aligned. P= attern > + guarantees that both memory accesses use the same base register, > + the offsets are constants within the range, and the gap between the o= ffsets is 4. > + If preload complete then check that registers are legal. WBACK indic= ates whether > + address is updated. LOAD indicates whether memory access is load or = store. */ ARM ARM terminology uses Rn for the base reg, so: s/RTN/RN/ > +bool > +operands_ok_ldrd_strd (rtx rt, rtx rt2, rtx rtn, HOST_WIDE_INT offset, s/rtn/rn/ > + bool wback, bool load) > +{ > + unsigned int t, t2, n; > + > + if (!reload_completed) > + return true; > + > + if (!offset_ok_for_ldrd_strd (offset)) > + return false; > + > + t =3D REGNO (rt); > + t2 =3D REGNO (rt2); > + n =3D REGNO (rtn); > + > + if ((TARGET_THUMB2) > + && ((wback && (n =3D=3D t || n =3D=3D t2)) > + || (t =3D=3D SP_REGNUM) > + || (t =3D=3D PC_REGNUM) > + || (t2 =3D=3D SP_REGNUM) > + || (t2 =3D=3D PC_REGNUM) > + || (!load && (n =3D=3D PC_REGNUM)) > + || (load && (t =3D=3D t2)) > + /* Triggers Cortex-M3 LDRD errata. */ > + || (!wback && load && fix_cm3_ldrd && (n =3D=3D t)))) > + return false; > + > + if ((TARGET_ARM) > + && ((wback && (n =3D=3D t || n =3D=3D t2)) > + || (t2 =3D=3D PC_REGNUM) > + || (t % 2 !=3D 0) /* First destination register is not even.= */ > + || (t2 !=3D t + 1) > + /* PC can be used as base register (for offset addressing only= ), > + but it is depricated. */ > + || (n =3D=3D PC_REGNUM))) > + return false; > + > + return true; > +} > + > =0C > /* Print a symbolic form of X to the debug file, F. */ > static void > diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md > index e9da56d..ed82634 100644 > --- a/gcc/config/arm/arm.md > +++ b/gcc/config/arm/arm.md > @@ -11472,6 +11472,99 @@ > " > ) > > +;; Patterns for LDRD/STRD in Thumb2 mode > + > +(define_insn "*thumb2_ldrd" > + [(set (match_operand:SI 0 "s_register_operand" "=3Dr") > + (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") > + (match_operand:SI 2 "ldrd_strd_offset_operand" = "Do")))) > + (set (match_operand:SI 3 "s_register_operand" "=3Dr") > + (mem:SI (plus:SI (match_dup 1) > + (match_operand:SI 4 "const_int_operand" ""))))] > + "TARGET_LDRD && TARGET_THUMB2 > + && (current_tune->prefer_ldrd_strd && !optimize_function_for_size_p= (cfun)) All these should be gated on "reload_completed" and not on the tune or=20 size optimization. > + && ((INTVAL (operands[2]) + 4) =3D=3D INTVAL (operands[4])) > + && (operands_ok_ldrd_strd (operands[0], operands[3], > + operands[1], INTVAL (operands[2]), > + false, true))" > + "ldrd%?\t%0, %3, [%1, %2]" > + [(set_attr "type" "load2") > + (set_attr "predicable" "yes")]) > + > +(define_insn "*thumb2_ldrd_base" > + [(set (match_operand:SI 0 "s_register_operand" "=3Dr") > + (mem:SI (match_operand:SI 1 "s_register_operand" "rk"))) > + (set (match_operand:SI 2 "s_register_operand" "=3Dr") > + (mem:SI (plus:SI (match_dup 1) > + (const_int 4))))] > + "TARGET_LDRD && TARGET_THUMB2 > + && (current_tune->prefer_ldrd_strd && !optimize_function_for_size_p= (cfun)) > + && (operands_ok_ldrd_strd (operands[0], operands[2], > + operands[1], 0, false, true))" > + "ldrd%?\t%0, %2, [%1]" > + [(set_attr "type" "load2") > + (set_attr "predicable" "yes")]) > + > +(define_insn "*thumb2_ldrd_base_neg" > + [(set (match_operand:SI 0 "s_register_operand" "=3Dr") > + (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk") > + (const_int -4)))) > + (set (match_operand:SI 2 "s_register_operand" "=3Dr") > + (mem:SI (match_dup 1)))] > + "TARGET_LDRD && TARGET_THUMB2 > + && (current_tune->prefer_ldrd_strd && !optimize_function_for_size_p= (cfun)) > + && (operands_ok_ldrd_strd (operands[0], operands[2], > + operands[1], -4, false, true))" > + "ldrd%?\t%0, %2, [%1, #-4]" > + [(set_attr "type" "load2") > + (set_attr "predicable" "yes")]) > + > +(define_insn "*thumb2_strd" > + [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk") > + (match_operand:SI 1 "ldrd_strd_offset_operand" = "Do"))) > + (match_operand:SI 2 "s_register_operand" "r")) > + (set (mem:SI (plus:SI (match_dup 0) > + (match_operand:SI 3 "const_int_operand" ""))) > + (match_operand:SI 4 "s_register_operand" "r"))] > + "TARGET_LDRD && TARGET_THUMB2 > + && (current_tune->prefer_ldrd_strd && !optimize_function_for_size_p= (cfun)) > + && ((INTVAL (operands[1]) + 4) =3D=3D INTVAL (operands[3])) > + && (operands_ok_ldrd_strd (operands[2], operands[4], > + operands[0], INTVAL (operands[1]), > + false, false))" > + "strd%?\t%2, %4, [%0, %1]" > + [(set_attr "type" "store2") > + (set_attr "predicable" "yes")]) > + > +(define_insn "*thumb2_strd_base" > + [(set (mem:SI (match_operand:SI 0 "s_register_operand" "rk")) > + (match_operand:SI 1 "s_register_operand" "r")) > + (set (mem:SI (plus:SI (match_dup 0) > + (const_int 4))) > + (match_operand:SI 2 "s_register_operand" "r"))] > + "TARGET_LDRD && TARGET_THUMB2 > + && (current_tune->prefer_ldrd_strd && !optimize_function_for_size_p= (cfun)) > + && (operands_ok_ldrd_strd (operands[1], operands[2], > + operands[0], 0, false, false))" > + "strd%?\t%1, %2, [%0]" > + [(set_attr "type" "store2") > + (set_attr "predicable" "yes")]) > + > +(define_insn "*thumb2_strd_base_neg" > + [(set (mem:SI (plus:SI (match_operand:SI 0 "s_register_operand" "rk") > + (const_int -4))) > + (match_operand:SI 1 "s_register_operand" "r")) > + (set (mem:SI (match_dup 0)) > + (match_operand:SI 2 "s_register_operand" "r"))] > + "TARGET_LDRD && TARGET_THUMB2 > + && (current_tune->prefer_ldrd_strd && !optimize_function_for_size_p= (cfun)) > + && (operands_ok_ldrd_strd (operands[1], operands[2], > + operands[0], -4, false, false))" > + "strd%?\t%1, %2, [%0, #-4]" > + [(set_attr "type" "store2") > + (set_attr "predicable" "yes")]) > + > + > ;; Load the load/store multiple patterns > (include "ldmstm.md") > > diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md > index b67df55..231d910 100644 > --- a/gcc/config/arm/constraints.md > +++ b/gcc/config/arm/constraints.md > @@ -31,7 +31,7 @@ > ;; 'H' was previously used for FPA. > > ;; The following multi-letter normal constraints have been used: > -;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Dv, Dy, Di, Dt, Dz > +;; in ARM/Thumb-2 state: Da, Db, Dc, Dd, Dn, Dl, DL, Do, Dv, Dy, Di, Dt,= Dz > ;; in Thumb-1 state: Pa, Pb, Pc, Pd, Pe > ;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py > > @@ -279,6 +279,12 @@ > (match_test "TARGET_32BIT > && imm_for_neon_inv_logic_operand (op, GET_MODE (op))"))) > > +(define_constraint "Do" > + "@internal > + In ARM/Thumb2 state valid offset for an ldrd/strd instruction." > + (and (match_code "const_int") > + (match_test "offset_ok_for_ldrd_strd (ival)"))) > + > (define_constraint "Dv" > "@internal > In ARM/Thumb-2 state a const_double which can be used with a VFP fcon= sts > diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md > index 8ae26ca..badb68b 100644 > --- a/gcc/config/arm/predicates.md > +++ b/gcc/config/arm/predicates.md > @@ -137,6 +137,10 @@ > (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) <=3D GET_MOD= E_BITSIZE (mode) > && ((unsigned HOST_WIDE_INT) INTVAL (op)) > 0"))) > > +(define_predicate "ldrd_strd_offset_operand" > + (and (match_operand 0 "const_int_operand") > + (match_test "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"))) > diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c > index f330da3..21d1aa8 100644 > --- a/gcc/config/arm/arm.c > +++ b/gcc/config/arm/arm.c > @@ -12130,6 +12130,9 @@ offset_ok_for_ldrd_strd (HOST_WIDE_INT offset) > { > HOST_WIDE_INT max_offset; > > + if (!TARGET_LDRD) > + return false; > + This seems to be in the wrong place. If we don't have ldrd then the=20 question as to what is a valid offset is irrelevant. > /* Offset must be a multiple of 4 in Thumb mode. */ > if (TARGET_THUMB2 && ((offset & 3) !=3D 0)) > return false; >