Dropping the first patch which does not work because at expand-time there
must not be pre-/post-modify addressing :-(
This solutions turns completely away from MEM and addressing modes:
It represents loads from the 16-bits address-spaces as UNSPEC.
The code is as expected now with the additional improvement that loads
to RAMPZ can be factored out if the value is known to be the same
(at least the LDI part; the OUT part is still needed).
Moreover, the code gets simpler because loading the value to OUT to
RAMPZ can be open coded and need not to be hidden in the insn because
reload cannot handle these complicated addresses.
And the patch fixes some more issues:
- avr_load_libgcc_p must only allow __flash because __load_3/4 use LPM.
- Resetting RAMPZ after ELPM for EBI-devices in avr_out_lpm was void in
some situations because of premature return.
This is fixed now; the new code is located in avr_load_lpm.
Test suite results look good. There is just a ICE for
gcc.target/avr/torture/addr-space-2-x.c -O3 -g
which appears to be PR middle-end/52472
Ok to commit?
* config/avr/avr-protos.h (avr_load_lpm): New prototype.
* config/avr/avr.c (avr_mode_dependent_address_p): New function.
(TARGET_MODE_DEPENDENT_ADDRESS_P): New define.
(avr_load_libgcc_p): Restrict to __flash loads.
(avr_out_lpm): Only handle 1-byte loads from __flash.
(avr_load_lpm): New function.
(adjust_insn_length): Handle ADJUST_LEN_LOAD_LPM.
* config/avr/avr.md (unspec): Add UNSPEC_LPM.
(load_<mode>_libgcc): Use UNSPEC_LPM instead of MEM.
(load_<mode>, load_<mode>_clobber): New insns.
(mov<mode>): For multi-byte move from non-generic
16-bit address spaces: Expand to load_<mode> resp.
(load<mode>_libgcc): Remove expander.
(split-lpmx): Remove split.
Georg-Johann Lay wrote:
> The problem with the PR is that lower-subreg.c happily splits multi-byte moves
> from address spaces without knowing anything about the additional costs this
> The TARGET_MODE_DEPENDENT_ADDRESS_P hook cannot be used for 16-bit addresses
> because that hook is not sensitive to address spaces, but is is used for the
> 24-bit address space to avoid subreg lowering for PSImode.
> For the 16-bit address spaces the mov expander now assigns the address
> by hand as post-increment.
> Luckily, post-increment is the only addressing mode that makes sense with the
> non-generic address spaces and there is no choice for the address register
> resp. addressing mode, anyway...
> This patch does not fix the PR issue, of course, it just avoids subreg
> by using/pretending mode-dependent addresses.
> Ok for trunk?
> PR rtl-optimization/52543
> * config/avr/avr.c (avr_mode_dependent_address_p): New function.
> (TARGET_MODE_DEPENDENT_ADDRESS_P): New define.
> * config/avr/avr.md (unspec): Add UNSPEC_LPM.
> (load_<mode>_libgcc): Use UNSPEC_LPM instead of MEM.
> (mov<mode>): For multi-byte move from non-generic
> 16-bit address spaces: Expand to use Z++ as address for
> inline code and use UNSPEC_LPM (Z) for code from libgcc.
> (load<mode>_libgcc): Remove expander.
> (split-lpmx): Remove split.