> I think this is a cross-target issue, unfortunately.  It applies to both
aarch64 (which sets WORD_REGISTER_OPERATIONS
> to 0) and sparc (which sets it to 1).
>
> I'd recommend not defining WORD_REGISTER_OPERATIONS if possible.
> I don't think it should be needed on modern targets and it restricts some
things in order to make others possible.  It
> also (IMO) makes RTL harder to reason about.
>
> This should mostly be irrelevant on RISCy targets.  These days, they
wouldn't be expected to provide a pattern that
> performs QImode addition and so the behaviour of such a pattern shouldn't
matter.  Instead, the fact that a target
> only has (say) 32-bit addition instructions is indicated by providing only
SImode addition optabs.  And like you say,
> PROMOTE_MODE can be used to say that subword values should be stored in
word_mode registers.
>
> If you have the right optabs and PROMOTE_MODE definitions (which it sounds
like you do), I expect that you'd get the
> behaviour that you want for op->+ above even without
WORD_REGISTER_OPERATIONS.

I've now tried removing WORD_REGISTER_OPERATIONS and the result is actually
the same, so I'll stick with that. As you say, when your operands for add /
sub / etc are SI only, it will always convert and operate at SI width. It
looks like GCC prefers to promote arithmetic parameters earlier when
compared to bitwise. With any bitwise it seems to prefer to keep smaller
registers (matching the source type) as long as possible and only sign
extend when returning the result. In practice it probably makes little odds,
but it's a shame it's not possible to promote operands earlier to take
advantage of sign / zero extend loads which do the extension for free rather
than always zero extending.

I tried removing PROMOTE_MODE entirely and actually got identical results in
terms of operand choice for arithmetic vs bitwise. This seems to be a pretty
standard definition across other backends --

#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
        if (GET_MODE_CLASS (MODE) == MODE_INT && GET_MODE_SIZE (MODE) < 4) \
                (MODE) = SImode;

But isn't obviously doing anything. LOAD_EXTEND_OP is defined as
ZERO_EXTEND, which seems to make sense. Any register loads narrower than the
register are zero extended by default unless sign_extend variants of memory
ops are used.

Reply via email to