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

Reply via email to