Patchwork [ARM,1/4] New RTL patterns for LDRD/STRD in Thumb mode

login
register
mail settings
Submitter Greta Yorsh
Date Oct. 19, 2012, 4:51 p.m.
Message ID <000401cdae1a$09231810$1b694830$@yorsh@arm.com>
Download mbox | patch
Permalink /patch/192774/
State New
Headers show

Comments

Greta Yorsh - Oct. 19, 2012, 4:51 p.m.
> -----Original Message-----
> From: Richard Earnshaw
> Sent: 19 October 2012 16:44
> 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
> 
> On 19/10/12 16:20, Greta Yorsh wrote:
> 
> > Removed the condition "!optimize_function_for_size_p (cfun))".
> >
> > The condition "current_tune->prefer_ldrd_strd" is needed because the
> > patterns
> > 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
> > that match this pattern.
> >
> 
> The point of the reload_completed is that these patterns have the
> potential to cause some problems if they somehow matched during earlier
> passes and the address base was an eliminable register.
> 

Thank you for the explanation. Here is an updated patch.

Regression tests and bootstrap in progress for the entire sequence, after
addressing all other comments as well. 

OK for trunk, if bootstrap successful?

Thanks,
Greta


ChangeLog


gcc/

2012-10-19  Sameera Deshpande  <sameera.deshpande@arm.com>
            Greta Yorsh  <Greta.Yorsh@arm.com>

        * 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.
Richard Earnshaw - Oct. 19, 2012, 4:57 p.m.
On 19/10/12 17:51, Greta Yorsh wrote:
>> -----Original Message-----
>> From: Richard Earnshaw
>> Sent: 19 October 2012 16:44
>> 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
>>
>> On 19/10/12 16:20, Greta Yorsh wrote:
>>
>>> Removed the condition "!optimize_function_for_size_p (cfun))".
>>>
>>> The condition "current_tune->prefer_ldrd_strd" is needed because the
>>> patterns
>>> 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
>>> that match this pattern.
>>>
>>
>> The point of the reload_completed is that these patterns have the
>> potential to cause some problems if they somehow matched during earlier
>> passes and the address base was an eliminable register.
>>
>
> Thank you for the explanation. Here is an updated patch.
>
> Regression tests and bootstrap in progress for the entire sequence, after
> addressing all other comments as well.
>
> OK for trunk, if bootstrap successful?
>
> Thanks,
> Greta
>
>
> ChangeLog
>
>
> gcc/
>
> 2012-10-19  Sameera Deshpande  <sameera.deshpande@arm.com>
>              Greta Yorsh  <Greta.Yorsh@arm.com>
>
>          * 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.
>

OK.

R.

Patch

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_INT *);
+extern bool offset_ok_for_ldrd_strd (HOST_WIDE_INT);
+extern bool operands_ok_ldrd_strd (rtx, rtx, rtx, HOST_WIDE_INT, bool, bool);
 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;
 }
 
+/* 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) != 0))
+    return false;
+
+  if (TARGET_THUMB2)
+    max_offset = 1020;
+  else if (TARGET_ARM)
+    max_offset = 255;
+  else
+    gcc_unreachable ();
+
+  return ((offset <= max_offset) && (offset >= -max_offset));
+}
+
+/* Checks whether the operands are valid for use in an LDRD/STRD instruction.
+   Assumes that RT, RT2, and RN are REG.  This is guaranteed by the patterns.
+   Assumes that the address in the base register RN 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.  */
+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 = REGNO (rt);
+  t2 = REGNO (rt2);
+  n = REGNO (rn);
+
+  if ((TARGET_THUMB2)
+      && ((wback && (n == t || n == t2))
+          || (t == SP_REGNUM)
+          || (t == PC_REGNUM)
+          || (t2 == SP_REGNUM)
+          || (t2 == PC_REGNUM)
+          || (!load && (n == PC_REGNUM))
+          || (load && (t == t2))
+          /* Triggers Cortex-M3 LDRD errata.  */
+          || (!wback && load && fix_cm3_ldrd && (n == t))))
+    return false;
+
+  if ((TARGET_ARM)
+      && ((wback && (n == t || n == t2))
+          || (t2 == PC_REGNUM)
+          || (t % 2 != 0)   /* First destination register is not even.  */
+          || (t2 != t + 1)
+          /* PC can be used as base register (for offset addressing only),
+             but it is depricated.  */
+          || (n == PC_REGNUM)))
+    return false;
+
+  return true;
+}
+
 
 /* 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 @@ 
 ""
 )
 
+;; Patterns for LDRD/STRD in Thumb2 mode
+
+(define_insn "*thumb2_ldrd"
+  [(set (match_operand:SI 0 "s_register_operand" "=r")
+        (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" "=r")
+        (mem:SI (plus:SI (match_dup 1)
+                         (match_operand:SI 4 "const_int_operand" ""))))]
+  "TARGET_LDRD && TARGET_THUMB2 && reload_completed
+     && current_tune->prefer_ldrd_strd
+     && ((INTVAL (operands[2]) + 4) == 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" "=r")
+        (mem:SI (match_operand:SI 1 "s_register_operand" "rk")))
+   (set (match_operand:SI 2 "s_register_operand" "=r")
+        (mem:SI (plus:SI (match_dup 1)
+                         (const_int 4))))]
+  "TARGET_LDRD && TARGET_THUMB2 && reload_completed
+     && 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" "=r")
+	(mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "rk")
+                         (const_int -4))))
+   (set (match_operand:SI 2 "s_register_operand" "=r")
+        (mem:SI (match_dup 1)))]
+  "TARGET_LDRD && TARGET_THUMB2 && reload_completed
+     && 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" "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 && reload_completed
+     && current_tune->prefer_ldrd_strd
+     && ((INTVAL (operands[1]) + 4) == 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 && reload_completed
+     && 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 && reload_completed
+     && 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")
 
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.
 
 ;; 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 "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)) <= GET_MODE_BITSIZE (mode)
 	&& ((unsigned HOST_WIDE_INT) INTVAL (op)) > 0")))
 
+(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")))