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.
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