https://gcc.gnu.org/g:236d6fef2479654b3011f8208e1bd7f078700109
commit r15-1840-g236d6fef2479654b3011f8208e1bd7f078700109 Author: Siarhei Volkau <lis8...@gmail.com> Date: Thu Jun 20 10:24:31 2024 +0300 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 <lis8...@gmail.com> Diff: --- gcc/config/arm/arm.cc | 10 ++---- gcc/config/arm/iterators.md | 3 ++ gcc/config/arm/thumb1.md | 37 +++++++++++++++++++++- .../gcc.target/arm/thumb1-load-store-64bit.c | 16 ++++++++++ 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 6dab65f493b..bb9c7c3b5c4 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 987602da1bf..b9ff01cb104 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 d7074b43f60..b4d7c6ea981 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 00000000000..167fa9ec876 --- /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 } } */