From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22997 invoked by alias); 19 Oct 2012 15:20:52 -0000 Received: (qmail 22988 invoked by uid 22791); 19 Oct 2012 15:20:51 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL,BAYES_00,KHOP_RCVD_UNTRUST,KHOP_THREADED,MSGID_MULTIPLE_AT,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_QE 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; Fri, 19 Oct 2012 15:20:45 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Fri, 19 Oct 2012 16:20:43 +0100 Received: from e103227vm ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Fri, 19 Oct 2012 16:20:41 +0100 From: "Greta Yorsh" To: "Richard Earnshaw" Cc: "GCC Patches" , "Ramana Radhakrishnan" , , References: <001601cda6f6$2b3fcea0$81bf6be0$@yorsh@arm.com> <001701cda6f8$5f19a9b0$1d4cfd10$@yorsh@arm.com> <508006D6.4090806@arm.com> In-Reply-To: <508006D6.4090806@arm.com> Subject: RE: [PATCH, ARM][1/4] New RTL patterns for LDRD/STRD in Thumb mode Date: Fri, 19 Oct 2012 15:44:00 -0000 Message-ID: <000001cdae0d$421f2e40$c65d8ac0$@yorsh@arm.com> MIME-Version: 1.0 X-MC-Unique: 112101916204301801 Content-Type: multipart/mixed; boundary="----=_NextPart_000_0001_01CDAE15.A3E39640" 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/msg01807.txt.bz2 This is a multi-part message in MIME format. ------=_NextPart_000_0001_01CDAE15.A3E39640 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable Content-length: 3419 On 18 October 2012 14:41, Richard Earnshaw wrote: > > +/* Checks whether the operands are valid for use in an LDRD/STRD instruction. > > + Assumes that RT, RT2, and RTN are REG. This is guaranteed by the patterns. > > + Assumes that the address in the base register RTN is word aligned. Pattern > > + guarantees that both memory accesses use the same base register, > > + the offsets are constants within the range, and the gap between the offsets is 4. > > + If preload complete then check that registers are legal. WBACK indicates whether > > + address is updated. LOAD indicates whether memory access is load or store. */ >=20 > ARM ARM terminology uses Rn for the base reg, so: >=20 > s/RTN/RN/ Fixed. >=20 > > +bool > > +operands_ok_ldrd_strd (rtx rt, rtx rt2, rtx rtn, HOST_WIDE_INT offset, >=20 > s/rtn/rn/ Fixed. > > +;; 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)) >=20 > All these should be gated on "reload_completed" and not on the tune or=20 > size optimization. Removed the condition "!optimize_function_for_size_p (cfun))". The condition "current_tune->prefer_ldrd_strd" is needed because the patterns=20 for LDRD/STRD appear before the patterns for LDM/STM that can match the same RTL (two register in the list). Condition "reload_completed" does not help with it because peephole optimizations in ldmstm.md may (after reload) create new RTL insn=20 that match this pattern. > > 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; > > + >=20 > 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. Moved this condition to predicates.md and constraints.md. Other uses of offset_ok_for_ldrd_strd are already guarded by the conditions. I am attaching a new version of this patch.=20 No regression on qemu for arm-none-eabi with cpu cortex-m4 and cortex-a15. Ok for trunk? Thank you, Greta ChangeLog gcc/ 2012-10-19 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 patterns. (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 (Do): New constraint. ------=_NextPart_000_0001_01CDAE15.A3E39640 Content-Type: text/plain; name=1-thumb-patterns.patch.txt Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="1-thumb-patterns.patch.txt" Content-length: 9359 diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 010e7fc..bfe96ea 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_IN= T *); +extern bool offset_ok_for_ldrd_strd (HOST_WIDE_INT); +extern bool operands_ok_ldrd_strd (rtx, rtx, rtx, HOST_WIDE_INT, bool, boo= l); 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 fc3a508..c60e62f 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -12185,6 +12185,75 @@ arm_pad_reg_upward (enum machine_mode mode, return !BYTES_BIG_ENDIAN; } =20 +/* 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 instructi= on. + Assumes that RT, RT2, and RN are REG. This is guaranteed by the patter= ns. + Assumes that the address in the base register RN is word aligned. Patt= ern + guarantees that both memory accesses use the same base register, + the offsets are constants within the range, and the gap between the off= sets is 4. + If preload complete then check that registers are legal. WBACK indicat= es whether + address is updated. LOAD indicates whether memory access is load or st= ore. */ +bool +operands_ok_ldrd_strd (rtx rt, rtx rt2, rtx rn, HOST_WIDE_INT offset, + 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 (rn); + + 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 7c80f91..3277561 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -11511,6 +11511,99 @@ "" ) =20 +;; 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" "D= o")))) + (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 + && ((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 + && (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 + && (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" "D= o"))) + (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 + && ((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 + && (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 + && (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") =20 diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index b67df55..1b4167e 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -31,7 +31,7 @@ ;; 'H' was previously used for FPA. =20 ;; 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 =20 @@ -279,6 +279,12 @@ (match_test "TARGET_32BIT && imm_for_neon_inv_logic_operand (op, GET_MODE (op))"))) =20 +(define_constraint "Do" + "@internal + In ARM/Thumb2 state valid offset for an ldrd/strd instruction." + (and (match_code "const_int") + (match_test "TARGET_LDRD && 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 fconsts diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index f55acbf..8f49450 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_MODE_B= ITSIZE (mode) && ((unsigned HOST_WIDE_INT) INTVAL (op)) > 0"))) =20 +(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"))) ------=_NextPart_000_0001_01CDAE15.A3E39640--