On 04/02/2026 09:40, tanshanshan wrote:
> The load_multiple_sequence function already supports ldm_case=5 to handle
> memory references with arbitrary ARM-encodable constant offsets (via
> const_ok_for_arm).  However, the corresponding store path in
> store_multiple_sequence lacked this capability, even though gen_stm_seq
> was prepared to handle stm_case=5.
> 
> The change adds a check similar to load_multiple_sequence: when the
> offset is not zero but can be encoded as an ARM immediate (using
> const_ok_for_arm), we now return stm_case = 5. This enables the
> generation of add+stm sequences for store operations, improving
> code size and maintaining consistency between load and store
> optimizations.
> 
> gcc/ChangeLog:
>     * config/arm/arm.c (store_multiple_sequence): Add support for
>     stm_case=5 using const_ok_for_arm to check offset encodability.
> 
> Signed-off-by: tanshanshan <[email protected]>
> ---
>  gcc/config/arm/arm.cc | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc
> index 0a1f6612d07..5861849daae 100644
> --- a/gcc/config/arm/arm.cc
> +++ b/gcc/config/arm/arm.cc
> @@ -14907,6 +14907,9 @@ store_multiple_sequence (rtx *operands, int nops, int 
> nops_total,
>      stm_case = 3; /* stmda */
>    else if (TARGET_32BIT && unsorted_offsets[order[nops - 1]] == -4)
>      stm_case = 4; /* stmdb */
> +  else if (const_ok_for_arm (unsorted_offsets[order[0]])
> +        || const_ok_for_arm (-unsorted_offsets[order[0]]))
> +    stm_case = 5;
>    else
>      return 0;
>  

On reflection, I don't think this is sufficient.  The problem is that in order 
to generate an STM operation in this case we need to first form a suitable base 
address.  But that means emitting an ADD instruction first that modifies a 
register, so that we get the sequence

   ADD     Rb, Rb, #nnn
   STM     Rb, {list... }

The problem here is that there are no checks that this changed sequence is 
valid.  There are two cases where it would not be:
1) Rb is in list, in which case this would store the wrong value to memory
2) Rb is used after this instruction, but in that case subsequent code will 
assume that Rb will still have the unadjusted base address.

We could potentially deal with 2) by re-subtracting #nnn from Rb after the STM, 
but it seems that would be unlikely to be profitable in general and the 
existing code does not try to do this.  There's no way of handling 1).

I don't see anything in the existing code to make these additional checks; 
which is, I suspect, why this case is not in fact handled (it might be a 
left-over from some early code that the developer removed for this very reason).

Note that the LDM case can handle this because it is loading values into 
registers.  That gives us a scratch register (one of the registers we will 
load) that we can use as the modified base, giving

   ADD     Rl1, Rb, #nnn
   LDM     Rl1, {Rl1, rest-of-list...}

So unfortunately, I don't think this patch is correct.  It could be fixed by 
adding the additional checks, but that might not be easy given the information 
available.

Many thanks for trying though.

R.

Reply via email to