cris: Reload using special-regs before general-regs
authorHans-Peter Nilsson <hp@axis.com>
Tue, 1 Feb 2022 23:00:10 +0000 (00:00 +0100)
committerHans-Peter Nilsson <hp@axis.com>
Wed, 2 Feb 2022 00:20:06 +0000 (01:20 +0100)
commit07a6c52c4cd145d20488c4823669a2d984ba2051
tree738efbfcf64ffdc163f94675428c6ab008c46c7c
parent9a7f14ef9b6b287d99b8240cdb43e8fe089ea9b3
cris: Reload using special-regs before general-regs

On code where reload has an effect (i.e. quite rarely, just enough to be
noticeable), this change gets code quality back to the situation prior
to "Remove CRIS v32 ACR artefacts".  We had from IRA a pseudoregister
marked to be reloaded from a union of all allocatable registers (here:
SPEC_GENNONACR_REGS) but where the register-class corresponding to the
constraint for the register-type alternative (here: GENERAL_REGS) was
*not* a subset of that class: SPEC_GENNONACR_REGS (and GENNONACR_REGS)
had a one-register "hole" for the ACR register, a register present in
GENERAL_REGS.

Code in reload.cc:find_reloads adds 4 to the cost of a register-type
alternative that is neither a subset of the preferred register class nor
vice versa and thus reload thinks it can't use.  It would be preferable
to look for a non-empty intersection of the two, and use that
intersection for that alternative, something that can't be expressed
because a register class can't be formed from a random register set.

The effect was here that the GENERAL_REGS to/from memory alternatives
("r") had their cost raised such that the SPECIAL_REGS alternatives
("x") looked better.  This happened to improve code quality just a
little bit compared to GENERAL_REGS being chosen.

Anyway, with the improved CRIS register-class topology, the
subset-checking code no longer has the GENERAL_REGS-demoting effect.
To get the same quality, we have to adjust the port such that
SPECIAL_REGS are specifically preferred when possible and advisible,
i.e. when there's at least two of those registers as for the CPU variant
with multiplication (which happens to be the variant maintained for
performance).

For the move-pattern, the obvious method may seem to simply "curse" the
constraints of some alternatives (by prepending one of the "?!^$"
characters) but that method can't be used, because we want the effect to
be conditional on the CPU variant.  It'd also be a shame to split the
"*movsi_internal<setcc><setnz><setnzvc>" into two CPU-variants (with
different cursing).  Iterators would help, but it still seems unwieldy.
Instead, add copies of the GENERAL_REGS variants (to the SPECIAL_REGS
alternatives) on the "other" side, and make use of the "enabled"
attribute to activate just the desired order of alternatives.

gcc:

* config/cris/cris.cc (cris_preferred_reload_class): Reject
"eliminated" registers and small-enough constants unless
reloaded into a class that is a subset of GENERAL_REGS.
* config/cris/cris.md (attribute "cpu_variant"): New.
(attribute "enabled"): Conditionalize on a matching attribute
cpu_variant, if specified.
("*movsi_internal<setcc><setnz><setnzvc>"): For moves to and from
memory, add cpu-variant-enabled variants for "r" alternatives on
the far side of the "x" alternatives, preferring the "x" ones
only for variants where MOF is present (in addition to SRP).
gcc/config/cris/cris.cc
gcc/config/cris/cris.md