https://gcc.gnu.org/g:a1bcce749cf2347820956d9f6bdaa03951421b15
commit r16-6775-ga1bcce749cf2347820956d9f6bdaa03951421b15 Author: Wilco Dijkstra <[email protected]> Date: Mon Jan 12 14:19:46 2026 +0000 AArch64: Improve immediate generation [PR 114528] Improve immediate generation to support 2-instruction MOV+ADD/SUB of 12-bit shifted immediate. Eg. long f1 (void) { return 0x123400567000; } now generates: mov x0, 20014547599360 add x0, x0, 5664768 ret gcc: PR target/114528 * config/aarch64/aarch64.cc (aarch64_check_mov_add_imm12): New function to check and emit MOV+ADD/SUB immediates. (aarch64_internal_mov_immediate): Add support for MOV+ADD/SUB immediates. gcc/testsuite: PR target/114528 * gcc.target/aarch64/pr114528.c: New test. Diff: --- gcc/config/aarch64/aarch64.cc | 30 +++++++++++- gcc/testsuite/gcc.target/aarch64/pr114528.c | 76 +++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 293afa52b3b3..4784d3dadc5c 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -4915,6 +4915,26 @@ aarch64_move_imm (unsigned HOST_WIDE_INT val, machine_mode mode) } +/* Return true is VAL is a move immediate that can be created by add/sub of the + 12-bit shifted immediate VAL2. If GENERATE is true, emit the sequence. */ +static inline bool +aarch64_check_mov_add_imm12 (rtx dest, unsigned HOST_WIDE_INT val, + unsigned HOST_WIDE_INT val2, bool generate) +{ + if (!aarch64_move_imm (val - val2, DImode)) + { + val2 = val2 < 0x1000000 ? val2 - 0x1000000 : val2 + 0x1000000; + if (!aarch64_move_imm (val - val2, DImode)) + return false; + } + if (generate) + { + emit_insn (gen_rtx_SET (dest, GEN_INT (val - val2))); + emit_insn (gen_adddi3 (dest, dest, GEN_INT (val2))); + } + return true; +} + static int aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate, machine_mode mode) @@ -5003,6 +5023,14 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate, } return 2; } + + /* Try a mov/bitmask immediate with a shifted add/sub. */ + val2 = val & 0xfff000; + val3 = val2 - ((val >> 32) & 0xfff000); + if (aarch64_check_mov_add_imm12 (dest, val, val2, generate) + || aarch64_check_mov_add_imm12 (dest, val, val2 - 0xfff000, generate) + || aarch64_check_mov_add_imm12 (dest, val, val3, generate)) + return 2; } /* Try a bitmask plus 2 movk to generate the immediate in 3 instructions. */ @@ -5073,7 +5101,7 @@ aarch64_internal_mov_immediate (rtx dest, rtx imm, bool generate, if (generate) emit_insn (gen_insv_immdi (dest, GEN_INT (i), GEN_INT ((val >> i) & 0xffff))); - num_insns ++; + num_insns++; } return num_insns; diff --git a/gcc/testsuite/gcc.target/aarch64/pr114528.c b/gcc/testsuite/gcc.target/aarch64/pr114528.c new file mode 100644 index 000000000000..9cfe15abc33c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr114528.c @@ -0,0 +1,76 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + + +/* +** f1: +** mov x0, 20014547599360 +** add x0, x0, 5664768 +** ret +*/ + +long f1 (void) +{ + return 0x123400567000; +} + +/* +** f2: +** mov x0, 20014547599360 +** sub x0, x0, #11112448 +** ret +*/ + +long f2 (void) +{ + return 0x1233ff567000; +} + +/* +** f3: +** mov x0, 1311673391471656959 +** add x0, x0, 5668864 +** ret +*/ + +long f3 (void) +{ + return 0x1234000000567fff; +} + +/* +** f4: +** mov x0, 1312236341425078271 +** sub x0, x0, #11108352 +** ret +*/ + +long f4 (void) +{ + return 0x1235ffffff567fff; +} + +/* +** f5: +** mov x0, 8102099357864587376 +** add x0, x0, 10600448 +** ret +*/ + +long f5 (void) +{ + return 0x7070707071123070; +} + +/* +** f6: +** mov x0, 8102099357864587376 +** sub x0, x0, #8273920 +** ret +*/ + +long f6 (void) +{ + return 0x707070706ff23070; +}
