On Wed, Jul 30, 2025 at 1:00 PM Georg-Johann Lay <[email protected]> wrote:
>
> Insn combine may come up with superfluous reg-reg moves, where the
> combine people say that these are no problem since reg-alloc is supposed
> to optimize them. The issue is that the lower-subreg pass sitting
> between combine and reg-alloc may split such moves, coming up with a zoo
> of subregs which are only handled poorly by the register allocator.
>
> This patch adds a new avr mini-pass that handles such cases.
I wonder, since you observe the subreg pass making a mess of such, whether
this would be a good thing to do within the subreg pass itself?
A comment on your pass after only a very brief quick look: using RTL-SSA
should make this much simpler in theory.
Richard.
> As an example, take
>
> int f_ffssi (long x)
> {
> return __builtin_ffsl (x);
> }
>
> where the two functions have the same interface, i.e. there are no extra
> moves required for the argument or for the return value. However,
>
> $ avr-gcc -S -Os -dp -mno-fuse-move ...
>
> f_ffssi:
> mov r20,r22 ; 29 [c=4 l=1] movqi_insn/0
> mov r21,r23 ; 30 [c=4 l=1] movqi_insn/0
> mov r22,r24 ; 31 [c=4 l=1] movqi_insn/0
> mov r23,r25 ; 32 [c=4 l=1] movqi_insn/0
> mov r25,r23 ; 33 [c=4 l=4] *movsi/0
> mov r24,r22
> mov r23,r21
> mov r22,r20
> rcall __ffssi2 ; 34 [c=16 l=1] *ffssihi2.libgcc
> ret ; 37 [c=0 l=1] return
>
> where all the moves add up to a no-op. The -mno-fuse-move option
> stops any attempts by the avr backend to clean up that mess.
>
> gcc/
> * config/avr/avr-passes.def (avr_pass_2moves): Insert after combine.
> * config/avr/avr-passes.cc (make_avr_pass_2moves): New function.
> (pass_data avr_pass_data_2moves): New static variable.
> (avr_pass_2moves): New rtl_opt_pass.
> * config/avr/avr-protos.h (make_avr_pass_2moves): New proto.
>
> Ok for trunk?
>
> Johann
>
> --