]> git.ipfire.org Git - thirdparty/gcc.git/commit
AVR: target/114100 - Better indirect accesses for reduced Tiny
authorGeorg-Johann Lay <avr@gjlay.de>
Thu, 29 Feb 2024 16:19:27 +0000 (17:19 +0100)
committerGeorg-Johann Lay <avr@gjlay.de>
Thu, 29 Feb 2024 19:39:58 +0000 (20:39 +0100)
commitcda3836161834c5f21f264885891fe4d0ce90da1
tree50bff4f80befdac6abd0350a0655088055ec4ccf
parent02ca9d3f0c5d2b0255df28f021834dd67ad79bc2
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.
gcc/common/config/avr/avr-common.cc
gcc/config/avr/avr-passes.def
gcc/config/avr/avr-protos.h
gcc/config/avr/avr.cc
gcc/config/avr/avr.md
gcc/config/avr/avr.opt
gcc/doc/invoke.texi