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

2012-10-19 Thread Greta Yorsh
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.  */
 
 ARM ARM terminology uses Rn for the base reg, so:
 
 s/RTN/RN/

Fixed.

 
  +bool
  +operands_ok_ldrd_strd (rtx rt, rtx rt2, rtx rtn, HOST_WIDE_INT offset,
 
 s/rtn/rn/

Fixed.

  +;; 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
  +  (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 
 size optimization.

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.

  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 
 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. 

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  sameera.deshpa...@arm.com
Greta Yorsh  greta.yo...@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.

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 

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

2012-10-19 Thread Richard Earnshaw

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.






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

2012-10-19 Thread Greta Yorsh
 -Original Message-
 From: Richard Earnshaw
 Sent: 19 October 2012 16:44
 To: Greta Yorsh
 Cc: GCC Patches; Ramana Radhakrishnan; ni...@redhat.com;
 p...@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.deshpa...@arm.com
Greta Yorsh  greta.yo...@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.
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

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

2012-10-19 Thread Richard Earnshaw

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; ni...@redhat.com;
p...@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.deshpa...@arm.com
 Greta Yorsh  greta.yo...@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.




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

2012-10-18 Thread Richard Earnshaw

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  sameera.deshpa...@arm.com
 Greta Yorsh  greta.yo...@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 (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, 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 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) != 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 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. 
 */


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 = REGNO (rt);
+  t2 = REGNO (rt2);
+  n = REGNO (rtn);
+
+  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 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 =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
+  (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 
size optimization.




+