diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2024-02-29 17:19:27 +0100 |
---|---|---|
committer | Georg-Johann Lay <avr@gjlay.de> | 2024-02-29 20:39:58 +0100 |
commit | cda3836161834c5f21f264885891fe4d0ce90da1 (patch) | |
tree | 50bff4f80befdac6abd0350a0655088055ec4ccf /gcc/function.cc | |
parent | 02ca9d3f0c5d2b0255df28f021834dd67ad79bc2 (diff) | |
download | gcc-cda3836161834c5f21f264885891fe4d0ce90da1.zip gcc-cda3836161834c5f21f264885891fe4d0ce90da1.tar.gz gcc-cda3836161834c5f21f264885891fe4d0ce90da1.tar.bz2 |
AVR: target/114100 - Better indirect accesses for reduced Tiny
The Reduced Tiny core does not support indirect addressing with offset,
which basically means that every indirect memory access with a size
of more than one byte is effectively POST_INC or PRE_DEC. The lack of
that addressing mode is currently handled by pretending to support it,
and then let the insn printers add and subtract again offsets as needed.
For example, the following C code
int vars[10];
void inc_var2 (void) {
++vars[2];
}
is compiled to:
ldi r30,lo8(vars) ; 14 [c=4 l=2] *movhi/4
ldi r31,hi8(vars)
subi r30,lo8(-(4)) ; 15 [c=8 l=6] *movhi/2
sbci r31,hi8(-(4))
ld r20,Z+
ld r21,Z
subi r30,lo8((4+1))
sbci r31,hi8((4+1))
subi r20,-1 ; 16 [c=4 l=2] *addhi3_clobber/1
sbci r21,-1
subi r30,lo8(-(4+1)) ; 17 [c=4 l=4] *movhi/3
sbci r31,hi8(-(4+1))
st Z,r21
st -Z,r20
where the code could be -- and with this patch actually is -- like
ldi r30,lo8(vars+4) ; 28 [c=4 l=2] *movhi/4
ldi r31,hi8(vars+4)
ld r20,Z+ ; 17 [c=8 l=2] *movhi/2
ld r21,Z+
subi r20,-1 ; 19 [c=4 l=2] *addhi3_clobber/1
sbci r21,-1
st -Z,r21 ; 30 [c=4 l=2] *movhi/3
st -Z,r20
This is achieved in two steps:
- A post-reload split into "real" instructions during .split2.
- A new avr-specific mini pass .avr-fuse-add that runs before
RTL peephole and that tries to combine the generated pointer
additions into memory accesses to form POST_INC or PRE_DEC.
gcc/
PR target/114100
* doc/invoke.texi (AVR Options) <-mfuse-add>: Document.
* config/avr/avr.opt (-mfuse-add=): New target option.
* common/config/avr/avr-common.cc (avr_option_optimization_table)
[OPT_LEVELS_1_PLUS]: Set -mfuse-add=1.
[OPT_LEVELS_2_PLUS]: Set -mfuse-add=2.
* config/avr/avr-passes.def (avr_pass_fuse_add): Insert new pass.
* config/avr/avr-protos.h (avr_split_tiny_move)
(make_avr_pass_fuse_add): New protos.
* config/avr/avr.md [AVR_TINY]: New post-reload splitter uses
avr_split_tiny_move to split indirect memory accesses.
(gen_move_clobbercc): New define_expand helper.
* config/avr/avr.cc (avr_pass_data_fuse_add): New pass data.
(avr_pass_fuse_add): New class from rtl_opt_pass.
(make_avr_pass_fuse_add, avr_split_tiny_move): New functions.
(reg_seen_between_p, emit_move_ccc, emit_move_ccc_after): New functions.
(avr_legitimate_address_p) [AVR_TINY]: Don't restrict offsets
of PLUS addressing for AVR_TINY.
(avr_regno_mode_code_ok_for_base_p) [AVR_TINY]: Ignore -mstrict-X.
(avr_out_plus_1) [AVR_TINY]: Tweak ++Y and --Y.
(avr_mode_code_base_reg_class) [AVR_TINY]: Always return POINTER_REGS.
Diffstat (limited to 'gcc/function.cc')
0 files changed, 0 insertions, 0 deletions