On 9/27/26 1:28 PM, Dominic P wrote:
When combine forms an invalid MEM address (plus X C), find_split_point
splits out X, or gives up if X is a register; neither helps when C is
not a valid offset either.  Split out C instead in that case, so that
I3 can keep X, for example a scaled index, in the address.  A valid
offset stays where it is, since splitting it out needs one more
register.  I2DEST receives the constant, so try_combine now checks that
it has the mode of the address.

On arm, ((volatile unsigned int *) 0x20a04000)[i] = v becomes a constant
load and str v, [rC, ri, lsl #2] instead of lsl, add, add and str; on
aarch64 a register plus a mov/movk constant is no longer added first.
A Raspberry Pi firmware (arm1176, -O2 -flto) shrinks by 96 bytes.

Bootstrapped and regression tested on x86_64-pc-linux-gnu, and regression
tested on arm-none-eabi and aarch64-linux-gnu.

Assisted-by: Claude Opus 5 (Anthropic)

gcc/ChangeLog:

        * combine.cc (address_constant_mode_mismatch_p): New function.
        (try_combine): Do not split out an address constant into an I2DEST
        of another mode.
        (find_split_point): Split out a MEM address constant that is not a
        valid offset.

gcc/testsuite/ChangeLog:

        * gcc.dg/rtl/aarch64/split-const-offset-1.c: New test.
        * gcc.dg/torture/split-const-offset-1.c: New test.
        * gcc.target/aarch64/split-const-offset-1.c: New test.
        * gcc.target/arm/split-const-offset-1.c: New test.
        * gcc.target/arm/split-const-offset-2.c: New test.

Signed-off-by: Dominic P <[email protected]>
---
OK for trunk?
Why do you have the !address_constant_mode_mismatch test?  It would seem that for x+C that the C is never going to match the mode of X because C is always VOIDmode.

@@ -5026,6 +5043,16 @@ find_split_point (rtx *loc, rtx_insn *insn, bool set_src)
              XEXP (XEXP (XEXP (x, 0), 0), 1) = tem;
            }
+ /* If the constant is not a valid offset, compute it separately.
+            Test with a pseudo: a virtual REG may accept any offset.  */
+         machine_mode address_mode = GET_MODE (XEXP (x, 0));
+         rtx base = alloca_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1);
+         rtx addr = alloca_rtx_fmt_ee (PLUS, address_mode, base,
+                                       XEXP (XEXP (x, 0), 1));
+         if (!memory_address_addr_space_p (GET_MODE (x), addr,
+                                           MEM_ADDR_SPACE (x)))
+           return &XEXP (XEXP (x, 0), 1);
Not sure what the alloca_raw_REG stuff you're doing here is.  It seems like you just need a random reg to test validity of a reg+d style address?  Why not just use the expression as-is rather than creating a new one?  Feels like I'm missing something here.

Jeff

Reply via email to