RE: [PATCH, ARM][1/4] New RTL patterns for LDRD/STRD in Thumb mode
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
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
-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
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
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. +