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;
+}

Reply via email to