about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWANG Rui <wangrui@loongson.cn>2025-06-12 17:07:36 +0800
committerWANG Rui <wangrui@loongson.cn>2025-06-14 09:39:30 +0800
commitc49ec838685eb54fbbc5acc55e9cb2947cad315e (patch)
treea5f912e5e8b12e5428bacc3d39c37e4d7f1630f1
parent8da623945f83933dd38644d5745532ee032e855b (diff)
downloadrust-c49ec838685eb54fbbc5acc55e9cb2947cad315e.tar.gz
rust-c49ec838685eb54fbbc5acc55e9cb2947cad315e.zip
Add `f16` inline asm support for LoongArch
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs21
-rw-r--r--compiler/rustc_target/src/asm/loongarch.rs8
-rw-r--r--tests/assembly/asm/loongarch-type.rs26
3 files changed, 51 insertions, 4 deletions
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 4185aef8b31..9ddadcf16aa 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -1021,6 +1021,15 @@ fn llvm_fixup_input<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
         }
+        (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F16) =>
+        {
+            // Smaller floats are always "NaN-boxed" inside larger floats on LoongArch.
+            let value = bx.bitcast(value, bx.type_i16());
+            let value = bx.zext(value, bx.type_i32());
+            let value = bx.or(value, bx.const_u32(0xFFFF_0000));
+            bx.bitcast(value, bx.type_f32())
+        }
         (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
@@ -1178,6 +1187,13 @@ fn llvm_fixup_output<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
         }
+        (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F16) =>
+        {
+            let value = bx.bitcast(value, bx.type_i32());
+            let value = bx.trunc(value, bx.type_i16());
+            bx.bitcast(value, bx.type_f16())
+        }
         (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
@@ -1318,6 +1334,11 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             cx.type_vector(cx.type_i16(), count)
         }
+        (LoongArch(LoongArchInlineAsmRegClass::freg), BackendRepr::Scalar(s))
+            if s.primitive() == Primitive::Float(Float::F16) =>
+        {
+            cx.type_f32()
+        }
         (Mips(MipsInlineAsmRegClass::reg), BackendRepr::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
diff --git a/compiler/rustc_target/src/asm/loongarch.rs b/compiler/rustc_target/src/asm/loongarch.rs
index 8783d3953b1..51e7ee8daa4 100644
--- a/compiler/rustc_target/src/asm/loongarch.rs
+++ b/compiler/rustc_target/src/asm/loongarch.rs
@@ -37,9 +37,11 @@ impl LoongArchInlineAsmRegClass {
         arch: InlineAsmArch,
     ) -> &'static [(InlineAsmType, Option<Symbol>)] {
         match (self, arch) {
-            (Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; },
-            (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F32; },
-            (Self::freg, _) => types! { f: F32; d: F64; },
+            (Self::reg, InlineAsmArch::LoongArch64) => {
+                types! { _: I8, I16, I32, I64, F16, F32, F64; }
+            }
+            (Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F16, F32; },
+            (Self::freg, _) => types! { f: F16, F32; d: F64; },
             _ => unreachable!("unsupported register class"),
         }
     }
diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs
index 86d9e03bc93..c782be19f1d 100644
--- a/tests/assembly/asm/loongarch-type.rs
+++ b/tests/assembly/asm/loongarch-type.rs
@@ -4,7 +4,7 @@
 //@ compile-flags: -Zmerge-functions=disabled
 //@ needs-llvm-components: loongarch
 
-#![feature(no_core)]
+#![feature(no_core, f16)]
 #![crate_type = "rlib"]
 #![no_core]
 #![allow(asm_sub_register, non_camel_case_types)]
@@ -69,6 +69,12 @@ check!(reg_i8, i8, reg, "move");
 // CHECK: #NO_APP
 check!(reg_i16, i16, reg, "move");
 
+// CHECK-LABEL: reg_f16:
+// CHECK: #APP
+// CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(reg_f16, f16, reg, "move");
+
 // CHECK-LABEL: reg_i32:
 // CHECK: #APP
 // CHECK: move ${{[a-z0-9]+}}, ${{[a-z0-9]+}}
@@ -99,6 +105,12 @@ check!(reg_f64, f64, reg, "move");
 // CHECK: #NO_APP
 check!(reg_ptr, ptr, reg, "move");
 
+// CHECK-LABEL: freg_f16:
+// CHECK: #APP
+// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check!(freg_f16, f16, freg, "fmov.s");
+
 // CHECK-LABEL: freg_f32:
 // CHECK: #APP
 // CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
@@ -123,6 +135,12 @@ check_reg!(r4_i8, i8, "$r4", "move");
 // CHECK: #NO_APP
 check_reg!(r4_i16, i16, "$r4", "move");
 
+// CHECK-LABEL: r4_f16:
+// CHECK: #APP
+// CHECK: move $a0, $a0
+// CHECK: #NO_APP
+check_reg!(r4_f16, f16, "$r4", "move");
+
 // CHECK-LABEL: r4_i32:
 // CHECK: #APP
 // CHECK: move $a0, $a0
@@ -153,6 +171,12 @@ check_reg!(r4_f64, f64, "$r4", "move");
 // CHECK: #NO_APP
 check_reg!(r4_ptr, ptr, "$r4", "move");
 
+// CHECK-LABEL: f0_f16:
+// CHECK: #APP
+// CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}
+// CHECK: #NO_APP
+check_reg!(f0_f16, f16, "$f0", "fmov.s");
+
 // CHECK-LABEL: f0_f32:
 // CHECK: #APP
 // CHECK: fmov.s $f{{[a-z0-9]+}}, $f{{[a-z0-9]+}}