From 84af199fde3013c5ef0afa45dfaf90fe30b451bd Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 30 Jun 2026 20:42:20 +0800 Subject: [PATCH] loongarch: Use `intrinsics::simd` for vldi --- .../src/loongarch64/lasx/generated.rs | 11 -- .../src/loongarch64/lasx/portable.rs | 184 ++++++++++++++++++ .../src/loongarch64/lsx/generated.rs | 11 -- .../core_arch/src/loongarch64/lsx/portable.rs | 94 +++++++++ crates/core_arch/src/loongarch64/simd.rs | 79 ++++++++ crates/stdarch-gen-loongarch/lasx.spec | 1 + crates/stdarch-gen-loongarch/lsx.spec | 1 + .../src/portable-intrinsics.txt | 2 + 8 files changed, 361 insertions(+), 22 deletions(-) diff --git a/crates/core_arch/src/loongarch64/lasx/generated.rs b/crates/core_arch/src/loongarch64/lasx/generated.rs index 3114797506..8e2bf10114 100644 --- a/crates/core_arch/src/loongarch64/lasx/generated.rs +++ b/crates/core_arch/src/loongarch64/lasx/generated.rs @@ -447,8 +447,6 @@ unsafe extern "unadjusted" { fn __lasx_xvssrln_h_w(a: __v8i32, b: __v8i32) -> __v16i16; #[link_name = "llvm.loongarch.lasx.xvssrln.w.d"] fn __lasx_xvssrln_w_d(a: __v4i64, b: __v4i64) -> __v8i32; - #[link_name = "llvm.loongarch.lasx.xvldi"] - fn __lasx_xvldi(a: i32) -> __v4i64; #[link_name = "llvm.loongarch.lasx.xvextl.qu.du"] fn __lasx_xvextl_qu_du(a: __v4u64) -> __v4u64; #[link_name = "llvm.loongarch.lasx.vext2xv.h.b"] @@ -2597,15 +2595,6 @@ pub fn lasx_xvssrln_w_d(a: m256i, b: m256i) -> m256i { unsafe { transmute(__lasx_xvssrln_w_d(transmute(a), transmute(b))) } } -#[inline] -#[target_feature(enable = "lasx")] -#[rustc_legacy_const_generics(0)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvldi() -> m256i { - static_assert_simm_bits!(IMM_S13, 13); - unsafe { transmute(__lasx_xvldi(IMM_S13)) } -} - #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] diff --git a/crates/core_arch/src/loongarch64/lasx/portable.rs b/crates/core_arch/src/loongarch64/lasx/portable.rs index 8d7b0e1d11..2f8bb33ab3 100644 --- a/crates/core_arch/src/loongarch64/lasx/portable.rs +++ b/crates/core_arch/src/loongarch64/lasx/portable.rs @@ -357,6 +357,7 @@ impl_sv!("lasx", lasx_xvrepli_b, simd_ext_splat, m256i, i8x32, 10); impl_sv!("lasx", lasx_xvrepli_h, simd_ext_splat, m256i, i16x16, 10); impl_sv!("lasx", lasx_xvrepli_w, simd_ext_splat, m256i, i32x8, 10); impl_sv!("lasx", lasx_xvrepli_d, simd_ext_splat, m256i, i64x4, 10); +impl_sv!("lasx", lasx_xvldi, simd_ext_ldi, m256i, i64x4, 13, const); impl_vvv!("lasx", lasx_xvadd_b, simd_add, m256i, i8x32); impl_vvv!("lasx", lasx_xvadd_h, simd_add, m256i, i16x16); @@ -618,3 +619,186 @@ impl_vvvv!("lasx", lasx_xvfnmsub_d, simd_ext_fnmsub, m256d, f64x4); impl_vugv!("lasx", lasx_xvinsgr2vr_w, simd_insert, m256i, i32x8, i32, 3); impl_vugv!("lasx", lasx_xvinsgr2vr_d, simd_insert, m256i, i64x4, i64, 2); + +#[cfg(test)] +mod tests { + use crate::{ + core_arch::{loongarch64::*, simd::*}, + mem::transmute, + }; + use stdarch_test::simd_test; + + #[simd_test(enable = "lasx")] + unsafe fn xvldi() { + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<0>())); + let r = i8x32::new( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + ); + assert_eq!(r, transmute(lasx_xvldi::<255>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<1024>())); + let r = i8x32::new( + 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, + -2, 0, -2, 0, -2, 0, -2, + ); + assert_eq!(r, transmute(lasx_xvldi::<1536>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<2048>())); + let r = i8x32::new( + 0, -2, -1, -1, 0, -2, -1, -1, 0, -2, -1, -1, 0, -2, -1, -1, 0, -2, -1, -1, 0, -2, -1, + -1, 0, -2, -1, -1, 0, -2, -1, -1, + ); + assert_eq!(r, transmute(lasx_xvldi::<2560>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<3072>())); + let r = i8x32::new( + 0, -2, -1, -1, -1, -1, -1, -1, 0, -2, -1, -1, -1, -1, -1, -1, 0, -2, -1, -1, -1, -1, + -1, -1, 0, -2, -1, -1, -1, -1, -1, -1, + ); + assert_eq!(r, transmute(lasx_xvldi::<3584>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-4096>())); + let r = i8x32::new( + -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, + 0, -128, 0, 0, 0, -128, 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3968>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3840>())); + let r = i8x32::new( + 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, + 0, 0, -128, 0, 0, 0, -128, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3712>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3584>())); + let r = i8x32::new( + 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, + 0, 0, 0, -128, 0, 0, 0, -128, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3456>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3328>())); + let r = i8x32::new( + 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, + -128, 0, 0, 0, -128, 0, 0, 0, -128, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3200>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-3072>())); + let r = i8x32::new( + -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, + 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2944>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2816>())); + let r = i8x32::new( + 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, + -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2688>())); + let r = i8x32::new( + -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, + 0, -1, 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2560>())); + let r = i8x32::new( + -1, -128, 0, 0, -1, -128, 0, 0, -1, -128, 0, 0, -1, -128, 0, 0, -1, -128, 0, 0, -1, + -128, 0, 0, -1, -128, 0, 0, -1, -128, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2432>())); + let r = i8x32::new( + -1, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, -1, + -1, 0, 0, -1, -1, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2304>())); + let r = i8x32::new( + -1, -1, -128, 0, -1, -1, -128, 0, -1, -1, -128, 0, -1, -1, -128, 0, -1, -1, -128, 0, + -1, -1, -128, 0, -1, -1, -128, 0, -1, -1, -128, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2176>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-2048>())); + let r = i8x32::new( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1793>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1792>())); + let r = i8x32::new( + 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, + -1, 0, -1, 0, -1, 0, -1, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1622>())); + let r = i8x32::new( + 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, + 64, 0, 0, 0, 64, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1536>())); + let r = i8x32::new( + 0, 0, 80, -63, 0, 0, 80, -63, 0, 0, 80, -63, 0, 0, 80, -63, 0, 0, 80, -63, 0, 0, 80, + -63, 0, 0, 80, -63, 0, 0, 80, -63, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1366>())); + let r = i8x32::new( + 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, + 0, 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1280>())); + let r = i8x32::new( + 0, 0, 80, -63, 0, 0, 0, 0, 0, 0, 80, -63, 0, 0, 0, 0, 0, 0, 80, -63, 0, 0, 0, 0, 0, 0, + 80, -63, 0, 0, 0, 0, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1110>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, + 0, 0, 0, 64, + ); + assert_eq!(r, transmute(lasx_xvldi::<-1024>())); + let r = i8x32::new( + 0, 0, 0, 0, 0, 0, 42, -64, 0, 0, 0, 0, 0, 0, 42, -64, 0, 0, 0, 0, 0, 0, 42, -64, 0, 0, + 0, 0, 0, 0, 42, -64, + ); + assert_eq!(r, transmute(lasx_xvldi::<-854>())); + } +} diff --git a/crates/core_arch/src/loongarch64/lsx/generated.rs b/crates/core_arch/src/loongarch64/lsx/generated.rs index 6483c6296a..869fe9052d 100644 --- a/crates/core_arch/src/loongarch64/lsx/generated.rs +++ b/crates/core_arch/src/loongarch64/lsx/generated.rs @@ -749,8 +749,6 @@ unsafe extern "unadjusted" { fn __lsx_vssrln_h_w(a: __v4i32, b: __v4i32) -> __v8i16; #[link_name = "llvm.loongarch.lsx.vssrln.w.d"] fn __lsx_vssrln_w_d(a: __v2i64, b: __v2i64) -> __v4i32; - #[link_name = "llvm.loongarch.lsx.vldi"] - fn __lsx_vldi(a: i32) -> __v2i64; #[link_name = "llvm.loongarch.lsx.vshuf.b"] fn __lsx_vshuf_b(a: __v16i8, b: __v16i8, c: __v16i8) -> __v16i8; #[link_name = "llvm.loongarch.lsx.vextl.qu.du"] @@ -3668,15 +3666,6 @@ pub fn lsx_vssrln_w_d(a: m128i, b: m128i) -> m128i { unsafe { transmute(__lsx_vssrln_w_d(transmute(a), transmute(b))) } } -#[inline] -#[target_feature(enable = "lsx")] -#[rustc_legacy_const_generics(0)] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vldi() -> m128i { - static_assert_simm_bits!(IMM_S13, 13); - unsafe { transmute(__lsx_vldi(IMM_S13)) } -} - #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] diff --git a/crates/core_arch/src/loongarch64/lsx/portable.rs b/crates/core_arch/src/loongarch64/lsx/portable.rs index a8a08372d6..d82c858953 100644 --- a/crates/core_arch/src/loongarch64/lsx/portable.rs +++ b/crates/core_arch/src/loongarch64/lsx/portable.rs @@ -251,6 +251,7 @@ impl_sv!("lsx", lsx_vrepli_b, simd_ext_splat, m128i, i8x16, 10); impl_sv!("lsx", lsx_vrepli_h, simd_ext_splat, m128i, i16x8, 10); impl_sv!("lsx", lsx_vrepli_w, simd_ext_splat, m128i, i32x4, 10); impl_sv!("lsx", lsx_vrepli_d, simd_ext_splat, m128i, i64x2, 10); +impl_sv!("lsx", lsx_vldi, simd_ext_ldi, m128i, i64x2, 13, const); impl_vvv!("lsx", lsx_vadd_b, simd_add, m128i, i8x16); impl_vvv!("lsx", lsx_vadd_h, simd_add, m128i, i16x8); @@ -520,3 +521,96 @@ impl_vugv!("lsx", lsx_vinsgr2vr_b, simd_insert, m128i, i8x16, i32, 4); impl_vugv!("lsx", lsx_vinsgr2vr_h, simd_insert, m128i, i16x8, i32, 3); impl_vugv!("lsx", lsx_vinsgr2vr_w, simd_insert, m128i, i32x4, i32, 2); impl_vugv!("lsx", lsx_vinsgr2vr_d, simd_insert, m128i, i64x2, i64, 1); + +#[cfg(test)] +mod tests { + use crate::{ + core_arch::{loongarch64::*, simd::*}, + mem::transmute, + }; + use stdarch_test::simd_test; + + #[simd_test(enable = "lsx")] + unsafe fn vldi() { + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<0>())); + let r = i8x16::new( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + ); + assert_eq!(r, transmute(lsx_vldi::<255>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<1024>())); + let r = i8x16::new(0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2, 0, -2); + assert_eq!(r, transmute(lsx_vldi::<1536>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<2048>())); + let r = i8x16::new(0, -2, -1, -1, 0, -2, -1, -1, 0, -2, -1, -1, 0, -2, -1, -1); + assert_eq!(r, transmute(lsx_vldi::<2560>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<3072>())); + let r = i8x16::new(0, -2, -1, -1, -1, -1, -1, -1, 0, -2, -1, -1, -1, -1, -1, -1); + assert_eq!(r, transmute(lsx_vldi::<3584>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-4096>())); + let r = i8x16::new(-128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-3968>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-3840>())); + let r = i8x16::new(0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-3712>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-3584>())); + let r = i8x16::new(0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0); + assert_eq!(r, transmute(lsx_vldi::<-3456>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-3328>())); + let r = i8x16::new(0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128, 0, 0, 0, -128); + assert_eq!(r, transmute(lsx_vldi::<-3200>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-3072>())); + let r = i8x16::new( + -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, + ); + assert_eq!(r, transmute(lsx_vldi::<-2944>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-2816>())); + let r = i8x16::new( + 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, 0, -128, + ); + assert_eq!(r, transmute(lsx_vldi::<-2688>())); + let r = i8x16::new(-1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-2560>())); + let r = i8x16::new( + -1, -128, 0, 0, -1, -128, 0, 0, -1, -128, 0, 0, -1, -128, 0, 0, + ); + assert_eq!(r, transmute(lsx_vldi::<-2432>())); + let r = i8x16::new(-1, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-2304>())); + let r = i8x16::new( + -1, -1, -128, 0, -1, -1, -128, 0, -1, -1, -128, 0, -1, -1, -128, 0, + ); + assert_eq!(r, transmute(lsx_vldi::<-2176>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-2048>())); + let r = i8x16::new( + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + ); + assert_eq!(r, transmute(lsx_vldi::<-1793>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-1792>())); + let r = i8x16::new(0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1); + assert_eq!(r, transmute(lsx_vldi::<-1622>())); + let r = i8x16::new(0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 64); + assert_eq!(r, transmute(lsx_vldi::<-1536>())); + let r = i8x16::new(0, 0, 80, -63, 0, 0, 80, -63, 0, 0, 80, -63, 0, 0, 80, -63); + assert_eq!(r, transmute(lsx_vldi::<-1366>())); + let r = i8x16::new(0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-1280>())); + let r = i8x16::new(0, 0, 80, -63, 0, 0, 0, 0, 0, 0, 80, -63, 0, 0, 0, 0); + assert_eq!(r, transmute(lsx_vldi::<-1110>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64); + assert_eq!(r, transmute(lsx_vldi::<-1024>())); + let r = i8x16::new(0, 0, 0, 0, 0, 0, 42, -64, 0, 0, 0, 0, 0, 0, 42, -64); + assert_eq!(r, transmute(lsx_vldi::<-854>())); + } +} diff --git a/crates/core_arch/src/loongarch64/simd.rs b/crates/core_arch/src/loongarch64/simd.rs index b6566b6435..1d83333e2f 100644 --- a/crates/core_arch/src/loongarch64/simd.rs +++ b/crates/core_arch/src/loongarch64/simd.rs @@ -146,6 +146,72 @@ pub(super) const unsafe fn simd_ext_ld(a: *const i8) -> T core::ptr::read_unaligned(a) } +#[inline(always)] +#[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")] +pub(super) const unsafe fn simd_ext_ldi() -> T { + use crate::core_arch::simd::{i8x8, i16x4, i32x2}; + use crate::mem::transmute; + + #[inline(always)] + const fn sext(v: i32, bits: u32) -> i64 { + ((v as i64) << (64 - bits)) >> (64 - bits) + } + + #[inline(always)] + const fn expand_u8(imm: i32) -> u64 { + let mut v = imm as u64; + v = (v | (v << 28)) & 0x0000000f0000000f; + v = (v | (v << 14)) & 0x0003000300030003; + v = (v | (v << 7)) & 0x0101010101010101; + v.wrapping_mul(0xff) + } + + #[inline(always)] + const fn fp32_imm(imm: i32) -> i32 { + ((imm & 0x80) << 24) + | ((!imm & 0x40) << 24) + | (((imm & 0x40) >> 6).wrapping_mul(0x1f) << 25) + | ((imm & 0x3f) << 19) + } + + #[inline(always)] + const fn fp64_imm(imm: i32) -> i64 { + ((((imm & 0x80) << 24) + | ((!imm & 0x40) << 24) + | (((imm & 0x40) >> 6).wrapping_mul(0xff) << 22) + | ((imm & 0x3f) << 16)) as i64) + << 32 + } + + let imm8 = I & 0xff; + let imm10 = I & 0x3ff; + + let r = if (I & 0x1000) == 0 { + match (I >> 10) & 3 { + 0 => transmute(i8x8::splat(imm8 as i8)), + 1 => transmute(i16x4::splat(sext(imm10, 10) as i16)), + 2 => transmute(i32x2::splat(sext(imm10, 10) as i32)), + 3 => sext(imm10, 10), + _ => unreachable!(), + } + } else { + match (I >> 8) & 0xf { + 0..=3 => transmute(i32x2::splat(imm8 << (8 * ((I >> 8) & 3)))), + 4..=5 => transmute(i16x4::splat((imm8 as i16) << (8 * ((I >> 8) & 1)))), + 6 => transmute(i32x2::splat((imm8 << 8) | 0xff)), + 7 => transmute(i32x2::splat((imm8 << 16) | 0xffff)), + 8 => transmute(i8x8::splat(imm8 as i8)), + 9 => expand_u8(imm8) as i64, + 10 => transmute(i32x2::splat(fp32_imm(I))), + 11 => transmute(i32x2::from_array([fp32_imm(I), 0])), + 12 => fp64_imm(I), + _ => unreachable!(), + } + }; + + simd_ext_splat(r) +} + #[inline(always)] #[rustc_const_unstable(feature = "stdarch_const_helpers", issue = "none")] pub(super) const unsafe fn simd_ext_ldx(a: *const i8, b: i64) -> T { @@ -315,6 +381,19 @@ macro_rules! impl_sv { } } }; + ($ft:literal, $name:ident, $op:ident, $oty:ty, $ity:ident, $ibs:expr, const) => { + #[inline] + #[target_feature(enable = $ft)] + #[rustc_legacy_const_generics(0)] + #[unstable(feature = "stdarch_loongarch", issue = "117427")] + pub fn $name() -> $oty { + static_assert_simm_bits!(IMM, $ibs); + unsafe { + let r: $ity = $op::(); + transmute(r) + } + } + }; } pub(super) use impl_sv; diff --git a/crates/stdarch-gen-loongarch/lasx.spec b/crates/stdarch-gen-loongarch/lasx.spec index d3efb6c960..2498264ef5 100644 --- a/crates/stdarch-gen-loongarch/lasx.spec +++ b/crates/stdarch-gen-loongarch/lasx.spec @@ -2696,6 +2696,7 @@ asm-fmts = xd, xj, xk data-types = UV32QI, UV32QI, UV32QI /// lasx_xvldi +impl = portable name = lasx_xvldi asm-fmts = xd, i13 data-types = V4DI, HI diff --git a/crates/stdarch-gen-loongarch/lsx.spec b/crates/stdarch-gen-loongarch/lsx.spec index 79dc4217da..01e7a0565e 100644 --- a/crates/stdarch-gen-loongarch/lsx.spec +++ b/crates/stdarch-gen-loongarch/lsx.spec @@ -3577,6 +3577,7 @@ asm-fmts = vd, vj, vk data-types = UV16QI, UV16QI, UV16QI /// lsx_vldi +impl = portable name = lsx_vldi asm-fmts = vd, i13 data-types = V2DI, HI diff --git a/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt b/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt index 0bd33c248b..be709509a0 100644 --- a/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt +++ b/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt @@ -293,6 +293,7 @@ lsx_vmuh_bu lsx_vmuh_hu lsx_vmuh_wu lsx_vmuh_du +lsx_vldi # LASX intrinsics lasx_xvsll_b @@ -587,3 +588,4 @@ lasx_xvmuh_bu lasx_xvmuh_hu lasx_xvmuh_wu lasx_xvmuh_du +lasx_xvldi