Rollup merge of #150826 - s390x-asm-f16-vector, r=uweigand,tgross35

Add `f16` inline ASM support for s390x

tracking issue: https://github.com/rust-lang/rust/issues/116909
cc https://github.com/rust-lang/rust/issues/125398

Support the `f16x8` type in inline assembly. Only with the `nnp-assist` feature are there any instructions that make use of this type. Based on the riscv implementation I now cast to `i16x8` when that feature is not enabled.

As far as I'm aware there are no instructions operating on `f16` scalar values. Should we still add support for using them in inline assembly?

r? @tgross35
cc @uweigand
This commit is contained in:
Jonathan Brouwer 2026-01-13 09:01:29 +01:00 committed by GitHub
commit 002b68d628
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 51 additions and 7 deletions

View file

@ -42,13 +42,13 @@ impl S390xInlineAsmRegClass {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg | Self::reg_addr => types! { _: I8, I16, I32, I64; },
Self::freg => types! { _: F32, F64; },
Self::freg => types! { _: F16, F32, F64; },
Self::vreg => {
if allow_experimental_reg {
// non-clobber-only vector register support is unstable.
types! {
vector: I32, F32, I64, F64, I128, F128,
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
vector: I32, F16, F32, I64, F64, I128, F128,
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF16(8), VecF32(4), VecF64(2);
}
} else {
&[]

View file

@ -6,8 +6,9 @@
//@[s390x_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector
//@[s390x_vector] needs-llvm-components: systemz
//@ compile-flags: -Zmerge-functions=disabled
//@ min-llvm-version: 21
#![feature(no_core, repr_simd, f128)]
#![feature(no_core, repr_simd, f16, f128)]
#![cfg_attr(s390x_vector, feature(asm_experimental_reg))]
#![crate_type = "rlib"]
#![no_core]
@ -27,6 +28,8 @@ pub struct i32x4([i32; 4]);
#[repr(simd)]
pub struct i64x2([i64; 2]);
#[repr(simd)]
pub struct f16x8([f16; 8]);
#[repr(simd)]
pub struct f32x4([f32; 4]);
#[repr(simd)]
pub struct f64x2([f64; 2]);
@ -35,6 +38,7 @@ 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 {}
@ -127,6 +131,12 @@ check!(reg_i32_addr, i32, reg_addr, "lgr");
// CHECK: #NO_APP
check!(reg_i64_addr, i64, reg_addr, "lgr");
// CHECK-LABEL: reg_f16:
// CHECK: #APP
// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}}
// CHECK: #NO_APP
check!(reg_f16, f16, freg, "ler");
// CHECK-LABEL: reg_f32:
// CHECK: #APP
// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}}
@ -173,6 +183,13 @@ check!(vreg_i32x4, i32x4, vreg, "vlr");
#[cfg(s390x_vector)]
check!(vreg_i64x2, i64x2, vreg, "vlr");
// s390x_vector-LABEL: vreg_f16x8:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f16x8, f16x8, vreg, "vlr");
// s390x_vector-LABEL: vreg_f32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
@ -208,6 +225,13 @@ check!(vreg_i64, i64, vreg, "vlr");
#[cfg(s390x_vector)]
check!(vreg_i128, i128, vreg, "vlr");
// s390x_vector-LABEL: vreg_f16:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check!(vreg_f16, f16, vreg, "vlr");
// s390x_vector-LABEL: vreg_f32:
// s390x_vector: #APP
// s390x_vector: vlr %v{{[0-9]+}}, %v{{[0-9]+}}
@ -253,6 +277,12 @@ check_reg!(r0_i32, i32, "r0", "lr");
// CHECK: #NO_APP
check_reg!(r0_i64, i64, "r0", "lr");
// CHECK-LABEL: f0_f16:
// CHECK: #APP
// CHECK: ler %f0, %f0
// CHECK: #NO_APP
check_reg!(f0_f16, f16, "f0", "ler");
// CHECK-LABEL: f0_f32:
// CHECK: #APP
// CHECK: ler %f0, %f0
@ -293,6 +323,13 @@ check_reg!(v0_i32x4, i32x4, "v0", "vlr");
#[cfg(s390x_vector)]
check_reg!(v0_i64x2, i64x2, "v0", "vlr");
// s390x_vector-LABEL: v0_f16x8:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f16x8, f16x8, "v0", "vlr");
// s390x_vector-LABEL: v0_f32x4:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
@ -328,6 +365,13 @@ check_reg!(v0_i64, i64, "v0", "vlr");
#[cfg(s390x_vector)]
check_reg!(v0_i128, i128, "v0", "vlr");
// s390x_vector-LABEL: v0_f16:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0
// s390x_vector: #NO_APP
#[cfg(s390x_vector)]
check_reg!(v0_f16, f16, "v0", "vlr");
// s390x_vector-LABEL: v0_f32:
// s390x_vector: #APP
// s390x_vector: vlr %v0, %v0

View file

@ -282,7 +282,7 @@ error: type `u8` cannot be used with this register class
LL | asm!("", in("v0") b);
| ^
|
= note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
= note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:95:28
@ -290,7 +290,7 @@ error: type `u8` cannot be used with this register class
LL | asm!("", out("v0") b);
| ^
|
= note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
= note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2
error: type `u8` cannot be used with this register class
--> $DIR/bad-reg.rs:108:35
@ -298,7 +298,7 @@ error: type `u8` cannot be used with this register class
LL | asm!("/* {} */", in(vreg) b);
| ^
|
= note: register class `vreg` supports these types: i32, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f32x4, f64x2
= note: register class `vreg` supports these types: i32, f16, f32, i64, f64, i128, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2
error: type `i32` cannot be used with this register class
--> $DIR/bad-reg.rs:120:27