From 4c558db7c8668c5241f4f70ae3d782e4c78619bb Mon Sep 17 00:00:00 2001
From: "rongfu.leng" <lenronfu@gmail.com>
Date: Thu, 27 Jun 2024 22:54:14 +0800
Subject: [PATCH] Enable f16 in assembly on aarch64 platforms that support it

Signed-off-by: rongfu.leng <lenronfu@gmail.com>
---
 compiler/rustc_target/src/asm/aarch64.rs |  6 ++---
 tests/assembly/asm/aarch64-types.rs      | 29 +++++++++++++++++++++++-
 tests/ui/asm/aarch64/type-check-3.stderr |  6 ++---
 tests/ui/asm/aarch64/type-f16.rs         | 21 +++++++++++++++++
 4 files changed, 55 insertions(+), 7 deletions(-)
 create mode 100644 tests/ui/asm/aarch64/type-f16.rs

diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs
index 1a3218da1af04..492d79f4e9513 100644
--- a/compiler/rustc_target/src/asm/aarch64.rs
+++ b/compiler/rustc_target/src/asm/aarch64.rs
@@ -57,11 +57,11 @@ impl AArch64InlineAsmRegClass {
         _arch: InlineAsmArch,
     ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match self {
-            Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
+            Self::reg => types! { _: I8, I16, I32, I64, F16, F32, F64; },
             Self::vreg | Self::vreg_low16 => types! {
-                neon: I8, I16, I32, I64, F32, F64,
+                neon: I8, I16, I32, I64, F16, F32, F64,
                     VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
-                    VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
+                    VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(4),VecF16(8), VecF32(4), VecF64(2);
             },
             Self::preg => &[],
         }
diff --git a/tests/assembly/asm/aarch64-types.rs b/tests/assembly/asm/aarch64-types.rs
index 3e2a4773703a3..4b506f180d83e 100644
--- a/tests/assembly/asm/aarch64-types.rs
+++ b/tests/assembly/asm/aarch64-types.rs
@@ -5,7 +5,7 @@
 //@ [arm64ec] compile-flags: --target arm64ec-pc-windows-msvc
 //@ [arm64ec] needs-llvm-components: aarch64
 
-#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch, f16)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
@@ -39,6 +39,10 @@ pub struct i32x2(i32, i32);
 #[repr(simd)]
 pub struct i64x1(i64);
 #[repr(simd)]
+pub struct f16x4(f16, f16, f16, f16);
+#[repr(simd)]
+pub struct f16x8(f16, f16, f16, f16, f16, f16, f16, f16);
+#[repr(simd)]
 pub struct f32x2(f32, f32);
 #[repr(simd)]
 pub struct f64x1(f64);
@@ -57,6 +61,7 @@ pub struct f64x2(f64, f64);
 
 impl Copy for i8 {}
 impl Copy for i16 {}
+impl Copy for f16 {}
 impl Copy for i32 {}
 impl Copy for f32 {}
 impl Copy for i64 {}
@@ -67,11 +72,13 @@ impl Copy for i16x4 {}
 impl Copy for i32x2 {}
 impl Copy for i64x1 {}
 impl Copy for f32x2 {}
+impl Copy for f16x4 {}
 impl Copy for f64x1 {}
 impl Copy for i8x16 {}
 impl Copy for i16x8 {}
 impl Copy for i32x4 {}
 impl Copy for i64x2 {}
+impl Copy for f16x8 {}
 impl Copy for f32x4 {}
 impl Copy for f64x2 {}
 
@@ -165,6 +172,12 @@ check!(reg_i16 i16 reg "mov" "");
 // CHECK: //NO_APP
 check!(reg_i32 i32 reg "mov" "");
 
+// CHECK-LABEL: reg_f16:
+// CHECK: @APP
+// CHECK: mov {{[a-z0-9]+}}, {{[a-z0-9]+}}
+// CHECK: @NO_APP
+check!(reg_f16 f16 reg "mov");
+
 // CHECK-LABEL: {{("#)?}}reg_f32{{"?}}
 // CHECK: //APP
 // CHECK: mov x{{[0-9]+}}, x{{[0-9]+}}
@@ -255,6 +268,20 @@ check!(vreg_i32x2 i32x2 vreg "fmov" "s");
 // CHECK: //NO_APP
 check!(vreg_i64x1 i64x1 vreg "fmov" "s");
 
+// neon-LABEL: vreg_f16x4:
+// neon: @APP
+// neon: vmov.f64 d{{[0-9]+}}, d{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(vreg_f16x4 f16x4 vreg "vmov.f64");
+
+// neon-LABEL: vreg_f16x8:
+// neon: @APP
+// neon: vorr q{{[0-9]+}}, q{{[0-9]+}}, q{{[0-9]+}}
+// neon: @NO_APP
+#[cfg(neon)]
+check!(vreg_f16x8 f16x8 vreg "vmov");
+
 // CHECK-LABEL: {{("#)?}}vreg_f32x2{{"?}}
 // CHECK: //APP
 // CHECK: fmov s{{[0-9]+}}, s{{[0-9]+}}
diff --git a/tests/ui/asm/aarch64/type-check-3.stderr b/tests/ui/asm/aarch64/type-check-3.stderr
index 9e37bb4c203f5..4bd97b93867bb 100644
--- a/tests/ui/asm/aarch64/type-check-3.stderr
+++ b/tests/ui/asm/aarch64/type-check-3.stderr
@@ -95,7 +95,7 @@ error: type `i128` cannot be used with this register class
 LL |         asm!("{}", in(reg) 0i128);
    |                            ^^^^^
    |
-   = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+   = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64
 
 error: type `float64x2_t` cannot be used with this register class
   --> $DIR/type-check-3.rs:75:28
@@ -103,7 +103,7 @@ error: type `float64x2_t` cannot be used with this register class
 LL |         asm!("{}", in(reg) f64x2);
    |                            ^^^^^
    |
-   = note: register class `reg` supports these types: i8, i16, i32, i64, f32, f64
+   = note: register class `reg` supports these types: i8, i16, i32, i64, f16, f32, f64
 
 error: type `Simd256bit` cannot be used with this register class
   --> $DIR/type-check-3.rs:77:29
@@ -111,7 +111,7 @@ error: type `Simd256bit` cannot be used with this register class
 LL |         asm!("{}", in(vreg) f64x4);
    |                             ^^^^^
    |
-   = note: register class `vreg` supports these types: i8, i16, i32, i64, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
+   = note: register class `vreg` supports these types: i8, i16, i32, i64, f16, f32, f64, i8x8, i16x4, i32x2, i64x1, f32x2, f64x1, i8x16, i16x8, i32x4, i64x2, f16x4, f16x8, f32x4, f64x2
 
 error: incompatible types for asm inout argument
   --> $DIR/type-check-3.rs:88:33
diff --git a/tests/ui/asm/aarch64/type-f16.rs b/tests/ui/asm/aarch64/type-f16.rs
new file mode 100644
index 0000000000000..763ea4684da37
--- /dev/null
+++ b/tests/ui/asm/aarch64/type-f16.rs
@@ -0,0 +1,21 @@
+//@ only-aarch64
+//@ run-pass
+
+#![feature(f16, f128)]
+use std::arch::asm;
+#[inline(never)]
+pub fn f32_to_f16_asm(a: f32) -> f16 {
+    let ret: f16;
+    unsafe {
+        asm!(
+        "fcvt    {ret:h}, {a:s}",
+        a = in(vreg) a,
+        ret = lateout(vreg) ret,
+        options(nomem, nostack),
+        );
+    }
+    ret
+}
+fn main() {
+    assert_eq!(f32_to_f16_asm(1.0 as f32), 1.0);
+}