James Boulton via Gcc <[email protected]> writes:
> I have a CPU which only operates on 32bit registers and as such define 
> WORD_REGISTER_OPERATIONS. This works well for arithmetic operations 
> (everything read to SI pseudo registers) but does not seem to apply to 
> bitwise operators. This generates marginally non-optimal code (additional 
> sign extends on result) and requires additional load instructions for QI and 
> HI registers which zero extend and are otherwise not required for anything 
> else.
>
> Is there any way to force the same SI pseudo register allocation for bitwise 
> operators as arithmetic? I have the usual PROMOTE_MODE to SImode defined, but 
> this doesn't appear to affect the pseudo register allocation.
>
> For example, the difference between & and + for "(int) return ptr[0] op 
> ptr[1];" for char *ptr --
>
> (insn 7 4 8 2 (set (reg:QI 31)
>         (mem:QI (reg/v/f:SI 28 [ ptr ]) [0 *ptr_5(D)+0 S1 A8])) "test.c":3:16 
> -1
>      (nil))
> (insn 8 7 9 2 (set (reg:QI 32)
>         (mem:QI (plus:SI (reg/v/f:SI 28 [ ptr ])
>                 (const_int 1 [0x1])) [0 MEM[(signed char *)ptr_5(D) + 1B]+0 
> S1 A8])) "test.c":3:16 -1
>      (nil))
> (insn 9 8 10 2 (set (reg:SI 33)
>         (and:SI (subreg:SI (reg:QI 31) 0)
>             (subreg:SI (reg:QI 32) 0))) "test.c":3:16 -1
>      (nil))
> (insn 10 9 11 2 (set (reg:SI 30 [ _6 ])
>         (sign_extend:SI (subreg:QI (reg:SI 33) 3))) "test.c":3:16 -1
>      (nil))
>
> (insn 7 4 8 2 (set (reg:SI 32 [ _2 ])
>         (sign_extend:SI (mem:QI (reg/v/f:SI 29 [ ptr ]) [0 *ptr_6(D)+0 S1 
> A8]))) "test.c":3:12 -1
>      (nil))
> (insn 8 7 9 2 (set (reg:SI 33 [ _4 ])
>         (sign_extend:SI (mem:QI (plus:SI (reg/v/f:SI 29 [ ptr ])
>                     (const_int 1 [0x1])) [0 MEM[(signed char *)ptr_6(D) + 
> 1B]+0 S1 A8]))) "test.c":3:21 -1
>      (nil))
> (insn 9 8 10 2 (set (reg:SI 31 [ _7 ])
>         (plus:SI (reg:SI 32 [ _2 ])
>             (reg:SI 33 [ _4 ]))) "test.c":3:16 -1
>      (nil))
>
> The arithmetic route allocates an SI register from the start and can 
> correctly sign extend the source compared to the bitwise route allocating QI 
> (zero extended) for the source, doing a full SI and anyway then sign 
> extending the result.

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.

Taking the documentation at face value:

  Define this macro to 1 if operations between registers with integral mode
  smaller than a word are always performed on the entire register.  To be
  more explicit, if you start with a pair of @code{word_mode} registers with
  known values and you do a subword, for example @code{QImode}, addition on
  the low part of the registers, then the compiler may consider that the
  result has a known value in @code{word_mode} too if the macro is defined
  to 1. [...]

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.

Thanks,
Richard

Reply via email to