On Sun, Sep 20, 2026 at 10:25 AM Matt Turner <[email protected]> wrote:
>
> The [r, w] alternatives of the SHORT extend patterns emit umov and smov,
> which are Advanced SIMD instructions, but they are guarded by the "fp"
> arch attribute. With -march=armv8-a+nosimd a 16-bit value in an FP
> register is therefore extended with an instruction the assembler
> rejects:
>
> unsigned int f (_Float16 x)
> {
> unsigned short s;
> __builtin_memcpy (&s, &x, sizeof (s));
> return s;
> }
>
> Error: selected processor does not support `umov w0,v0.h[0]'
>
> Guard both alternatives with "base_simd" instead, so that without SIMD
> the value is extended from memory.
>
> gcc/ChangeLog:
>
> * config/aarch64/aarch64.md (*extend<SHORT:mode><GPI:mode>2_aarch64):
> Guard the smov alternative with base_simd rather than fp.
> (*zero_extend<SHORT:mode><GPI:mode>2_aarch64): Likewise for umov.
Ok.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/aarch64/nosimd-extend.c: New test.
> ---
> gcc/config/aarch64/aarch64.md | 18 +++++++-------
> .../gcc.target/aarch64/nosimd-extend.c | 24 +++++++++++++++++++
> 2 files changed, 33 insertions(+), 9 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/aarch64/nosimd-extend.c
>
> diff --git ./gcc/config/aarch64/aarch64.md ./gcc/config/aarch64/aarch64.md
> index 4ae5c074cd1..a32f8c627f1 100644
> --- ./gcc/config/aarch64/aarch64.md
> +++ ./gcc/config/aarch64/aarch64.md
> @@ -2666,10 +2666,10 @@
> [(set (match_operand:GPI 0 "register_operand")
> (sign_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
> ""
> - {@ [ cons: =0 , 1 ; attrs: type , arch ]
> - [ r , r ; extend , * ] sxt<SHORT:extsize>\t%<GPI:w>0, %w1
> - [ r , m ; load_4 , * ] ldrs<SHORT:extsize>\t%<GPI:w>0, %1
> - [ r , w ; neon_to_gp , fp ] smov\t%<GPI:w>0,
> %1.<SHORT:size>[0]
> + {@ [ cons: =0 , 1 ; attrs: type , arch ]
> + [ r , r ; extend , * ]
> sxt<SHORT:extsize>\t%<GPI:w>0, %w1
> + [ r , m ; load_4 , * ]
> ldrs<SHORT:extsize>\t%<GPI:w>0, %1
> + [ r , w ; neon_to_gp , base_simd ] smov\t%<GPI:w>0,
> %1.<SHORT:size>[0]
> }
> )
>
> @@ -2677,11 +2677,11 @@
> [(set (match_operand:GPI 0 "register_operand")
> (zero_extend:GPI (match_operand:SHORT 1 "nonimmediate_operand")))]
> ""
> - {@ [ cons: =0 , 1 ; attrs: type , arch ]
> - [ r , r ; logic_imm , * ] and\t%<GPI:w>0, %<GPI:w>1,
> <SHORT:short_mask>
> - [ r , m ; load_4 , * ] ldr<SHORT:size>\t%w0, %1
> - [ w , m ; f_loads , fp ] ldr\t%<SHORT:size>0, %1
> - [ r , w ; neon_to_gp , fp ] umov\t%w0, %1.<SHORT:size>[0]
> + {@ [ cons: =0 , 1 ; attrs: type , arch ]
> + [ r , r ; logic_imm , * ] and\t%<GPI:w>0, %<GPI:w>1,
> <SHORT:short_mask>
> + [ r , m ; load_4 , * ] ldr<SHORT:size>\t%w0, %1
> + [ w , m ; f_loads , fp ] ldr\t%<SHORT:size>0, %1
> + [ r , w ; neon_to_gp , base_simd ] umov\t%w0, %1.<SHORT:size>[0]
> }
> )
>
> diff --git ./gcc/testsuite/gcc.target/aarch64/nosimd-extend.c
> ./gcc/testsuite/gcc.target/aarch64/nosimd-extend.c
> new file mode 100644
> index 00000000000..ce5dce389f3
> --- /dev/null
> +++ ./gcc/testsuite/gcc.target/aarch64/nosimd-extend.c
> @@ -0,0 +1,24 @@
> +/* { dg-do assemble } */
> +/* { dg-options "-O2 -march=armv8-a+nosimd -save-temps" } */
> +
> +/* umov and smov are Advanced SIMD instructions, so they must not be used
> + to move a 16-bit value out of an FP register when SIMD is disabled. */
> +
> +unsigned int
> +zext (_Float16 x)
> +{
> + unsigned short s;
> + __builtin_memcpy (&s, &x, sizeof (s));
> + return s;
> +}
> +
> +int
> +sext (_Float16 x)
> +{
> + short s;
> + __builtin_memcpy (&s, &x, sizeof (s));
> + return s;
> +}
> +
> +/* { dg-final { scan-assembler-not {\tumov\t} } } */
> +/* { dg-final { scan-assembler-not {\tsmov\t} } } */
> --
> 2.54.0
>