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
Passes regress, OK for commit?
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 --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index
293afa52b3b38781b765ca939ed51c280313bab4..4784d3dadc5c8811e84d042bcb24cf2928520219
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
0000000000000000000000000000000000000000..9cfe15abc33cddfb42175fd254f0bf8c06cbb564
--- /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;
+}