On Mon, Jan 12, 2026 at 10:13 AM Wilco Dijkstra <[email protected]> wrote:
>
>
> 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?

I am trying to compare this to what Eikansh implemented last year:
https://patchwork.sourceware.org/project/gcc/patch/[email protected]/
He is in the process of updating his patch (other things came up internally).
One thing he had noticed while working on it was that putting it too
early meant that the 2 instruction mov/movk form was not being
generated  when they still should be.
mov/movk form is fused on some micro-arch (AARCH64_FUSE_MOV_MOVK) so
we had wanted to keep that output around.
For an example his f4 (0xffffffff0001fedc) would be better if done
using mov/movk rather than mov/sub.

Thanks,
Andrew


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

Reply via email to