aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSiarhei Volkau <lis8215@gmail.com>2024-06-20 10:24:31 +0300
committerRichard Earnshaw <rearnsha@arm.com>2024-07-04 10:40:23 +0100
commit236d6fef2479654b3011f8208e1bd7f078700109 (patch)
tree055695afba9d22ca3423d59f2226f86bab034af6 /gcc
parent11049cdf204bc96bc407e5dd44ed3b8a492f405a (diff)
downloadgcc-236d6fef2479654b3011f8208e1bd7f078700109.zip
gcc-236d6fef2479654b3011f8208e1bd7f078700109.tar.gz
gcc-236d6fef2479654b3011f8208e1bd7f078700109.tar.bz2
arm: Use LDMIA/STMIA for thumb1 DI/DF loads/stores
If the address register is dead after load/store operation it looks beneficial to use LDMIA/STMIA instead of pair of LDR/STR instructions, at least if optimizing for size. gcc/ChangeLog: * config/arm/arm.cc (thumb_load_double_from_address): Emit ldmia when address reg rewritten by load. * config/arm/thumb1.md (peephole2 to rewrite DI/DF load): New. (peephole2 to rewrite DI/DF store): New. * config/arm/iterators.md (DIDF): New. gcc/testsuite: * gcc.target/arm/thumb1-load-store-64bit.c: Add new test. Signed-off-by: Siarhei Volkau <lis8215@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/arm/arm.cc10
-rw-r--r--gcc/config/arm/iterators.md3
-rw-r--r--gcc/config/arm/thumb1.md37
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb1-load-store-64bit.c16
4 files changed, 58 insertions, 8 deletions
diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
index 6dab65f..bb9c7c3 100644
--- a/gcc/config/arm/arm.cc
+++ b/gcc/config/arm/arm.cc
@@ -28374,15 +28374,11 @@ thumb_load_double_from_address (rtx *operands)
switch (GET_CODE (addr))
{
case REG:
- operands[2] = adjust_address (operands[1], SImode, 4);
-
- if (REGNO (operands[0]) == REGNO (addr))
- {
- output_asm_insn ("ldr\t%H0, %2", operands);
- output_asm_insn ("ldr\t%0, %1", operands);
- }
+ if (reg_overlap_mentioned_p (addr, operands[0]))
+ output_asm_insn ("ldmia\t%m1, {%0, %H0}", operands);
else
{
+ operands[2] = adjust_address (operands[1], SImode, 4);
output_asm_insn ("ldr\t%0, %1", operands);
output_asm_insn ("ldr\t%H0, %2", operands);
}
diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md
index 987602d..b9ff01c 100644
--- a/gcc/config/arm/iterators.md
+++ b/gcc/config/arm/iterators.md
@@ -50,6 +50,9 @@
;; A list of the 32bit and 64bit integer modes
(define_mode_iterator SIDI [SI DI])
+;; A list of the 64bit modes for thumb1.
+(define_mode_iterator DIDF [DI DF])
+
;; A list of atomic compare and swap success return modes
(define_mode_iterator CCSI [(CC_Z "TARGET_32BIT") (SI "TARGET_THUMB1")])
diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
index d7074b4..b4d7c6e 100644
--- a/gcc/config/arm/thumb1.md
+++ b/gcc/config/arm/thumb1.md
@@ -655,6 +655,42 @@
(set_attr "pool_range" "*,*,*,*,*,*,1018,*,*")]
)
+
+;; match patterns usable by ldmia/stmia
+(define_peephole2
+ [(set (match_operand:DIDF 0 "low_register_operand" "")
+ (match_operand:DIDF 1 "memory_operand" ""))]
+ "TARGET_THUMB1
+ && low_register_operand (XEXP (operands[1], 0), SImode)
+ && !reg_overlap_mentioned_p (XEXP (operands[1], 0), operands[0])
+ && peep2_reg_dead_p (1, XEXP (operands[1], 0))"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ {
+ operands[1] = change_address (operands[1], VOIDmode,
+ gen_rtx_POST_INC (SImode,
+ XEXP (operands[1], 0)));
+ }
+)
+
+(define_peephole2
+ [(set (match_operand:DIDF 0 "memory_operand" "")
+ (match_operand:DIDF 1 "low_register_operand" ""))]
+ "TARGET_THUMB1
+ && low_register_operand (XEXP (operands[0], 0), SImode)
+ && peep2_reg_dead_p (1, XEXP (operands[0], 0))
+ /* The low register in the transfer list may overlap the address,
+ but the second cannot. */
+ && REGNO (XEXP (operands[0], 0)) != (REGNO (operands[1]) + 1)"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ {
+ operands[0] = change_address (operands[0], VOIDmode,
+ gen_rtx_POST_INC (SImode,
+ XEXP (operands[0], 0)));
+ }
+)
+
(define_insn "*thumb1_movsi_insn"
[(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,r,l,l,l,>,l, l, m,*l*h*k")
(match_operand:SI 1 "general_operand" "l, I,j,J,K,>,l,i, mi,l,*l*h*k"))]
@@ -2055,4 +2091,3 @@
(set_attr "conds" "clob")
(set_attr "type" "multiple")]
)
-
diff --git a/gcc/testsuite/gcc.target/arm/thumb1-load-store-64bit.c b/gcc/testsuite/gcc.target/arm/thumb1-load-store-64bit.c
new file mode 100644
index 0000000..167fa9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb1-load-store-64bit.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb1_ok } */
+
+void copy_df(double *dst, const double *src)
+{
+ *dst = *src;
+}
+
+void copy_di(unsigned long long *dst, const unsigned long long *src)
+{
+ *dst = *src;
+}
+
+/* { dg-final { scan-assembler-times "ldmia\tr\[0-7\]" 2 } } */
+/* { dg-final { scan-assembler-times "stmia\tr\[0-7\]!" 2 } } */