Skip to content

Commit 9088dd7

Browse files
committed
add vec_mergel and vec_mergeh
1 parent 5f1b287 commit 9088dd7

File tree

1 file changed

+142
-0
lines changed

1 file changed

+142
-0
lines changed

crates/core_arch/src/s390x/vector.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,114 @@ mod sealed {
11241124
transmute(transmute::<_, vector_signed_long_long>(self).vec_revb())
11251125
}
11261126
}
1127+
1128+
#[repr(simd)]
1129+
struct MergeMask<const N: usize>([u32; N]);
1130+
1131+
impl<const N: usize> MergeMask<N> {
1132+
const fn merge_low() -> Self {
1133+
let mut mask = [0; N];
1134+
let mut i = N / 2;
1135+
let mut index = 0;
1136+
while index < N {
1137+
mask[index] = i as u32;
1138+
mask[index + 1] = (i + N) as u32;
1139+
1140+
i += 1;
1141+
index += 2;
1142+
}
1143+
MergeMask(mask)
1144+
}
1145+
1146+
const fn merge_high() -> Self {
1147+
let mut mask = [0; N];
1148+
let mut i = 0;
1149+
let mut index = 0;
1150+
while index < N {
1151+
mask[index] = i as u32;
1152+
mask[index + 1] = (i + N) as u32;
1153+
1154+
i += 1;
1155+
index += 2;
1156+
}
1157+
MergeMask(mask)
1158+
}
1159+
}
1160+
1161+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1162+
pub trait VectorMergel {
1163+
unsafe fn vec_mergel(self, other: Self) -> Self;
1164+
}
1165+
1166+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1167+
pub trait VectorMergeh {
1168+
unsafe fn vec_mergeh(self, other: Self) -> Self;
1169+
}
1170+
1171+
macro_rules! impl_merge {
1172+
($($ty:ident, $mergel:ident, $mergeh:ident),*) => {
1173+
$(
1174+
#[inline]
1175+
#[target_feature(enable = "vector")]
1176+
#[cfg_attr(test, assert_instr($mergel))]
1177+
unsafe fn $mergel(a: $ty, b: $ty) -> $ty {
1178+
const N: usize = core::mem::size_of::<$ty>() / core::mem::size_of::<l_t_t!($ty)>();
1179+
simd_shuffle(a, b, const { MergeMask::<N>::merge_low() })
1180+
}
1181+
1182+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1183+
impl VectorMergel for $ty {
1184+
#[inline]
1185+
#[target_feature(enable = "vector")]
1186+
unsafe fn vec_mergel(self, other: Self) -> Self {
1187+
$mergel(self, other)
1188+
}
1189+
}
1190+
1191+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1192+
impl VectorMergel for t_u!($ty) {
1193+
#[inline]
1194+
#[target_feature(enable = "vector")]
1195+
unsafe fn vec_mergel(self, other: Self) -> Self {
1196+
transmute($mergel(transmute(self), transmute(other)))
1197+
}
1198+
}
1199+
1200+
#[inline]
1201+
#[target_feature(enable = "vector")]
1202+
#[cfg_attr(test, assert_instr($mergeh))]
1203+
unsafe fn $mergeh(a: $ty, b: $ty) -> $ty {
1204+
const N: usize = core::mem::size_of::<$ty>() / core::mem::size_of::<l_t_t!($ty)>();
1205+
simd_shuffle(a, b, const { MergeMask::<N>::merge_high() })
1206+
}
1207+
1208+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1209+
impl VectorMergeh for $ty {
1210+
#[inline]
1211+
#[target_feature(enable = "vector")]
1212+
unsafe fn vec_mergeh(self, other: Self) -> Self {
1213+
$mergeh(self, other)
1214+
}
1215+
}
1216+
1217+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1218+
impl VectorMergeh for t_u!($ty) {
1219+
#[inline]
1220+
#[target_feature(enable = "vector")]
1221+
unsafe fn vec_mergeh(self, other: Self) -> Self {
1222+
transmute($mergeh(transmute(self), transmute(other)))
1223+
}
1224+
}
1225+
)*
1226+
}
1227+
}
1228+
1229+
impl_merge! {
1230+
vector_signed_char, vmrlb, vmrhb,
1231+
vector_signed_short, vmrlh, vmrhh,
1232+
vector_signed_int, vmrlf, vmrhf,
1233+
vector_signed_long_long, vmrlg, vmrhg
1234+
}
11271235
}
11281236

11291237
/// Vector element-wise addition.
@@ -1606,6 +1714,28 @@ where
16061714
a.vec_revb()
16071715
}
16081716

1717+
/// Merges the most significant ("high") halves of two vectors.
1718+
#[inline]
1719+
#[target_feature(enable = "vector")]
1720+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1721+
pub unsafe fn vec_mergeh<T>(a: T, b: T) -> T
1722+
where
1723+
T: sealed::VectorMergeh,
1724+
{
1725+
a.vec_mergeh(b)
1726+
}
1727+
1728+
/// Merges the least significant ("low") halves of two vectors.
1729+
#[inline]
1730+
#[target_feature(enable = "vector")]
1731+
#[unstable(feature = "stdarch_s390x", issue = "135681")]
1732+
pub unsafe fn vec_mergel<T>(a: T, b: T) -> T
1733+
where
1734+
T: sealed::VectorMergel,
1735+
{
1736+
a.vec_mergel(b)
1737+
}
1738+
16091739
#[cfg(test)]
16101740
mod tests {
16111741
use super::*;
@@ -1966,4 +2096,16 @@ mod tests {
19662096
[0xAABBCCDD, 0xEEFF0011, 0x22334455, 0x66778899],
19672097
[0xDDCCBBAA, 0x1100FFEE, 0x55443322, 0x99887766]
19682098
}
2099+
2100+
test_vec_2! { test_vec_mergeh_u32, vec_mergeh, u32x4,
2101+
[0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD],
2102+
[0x00000000, 0x11111111, 0x22222222, 0x33333333],
2103+
[0xAAAAAAAA, 0x00000000, 0xBBBBBBBB, 0x11111111]
2104+
}
2105+
2106+
test_vec_2! { test_vec_mergel_u32, vec_mergel, u32x4,
2107+
[0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC, 0xDDDDDDDD],
2108+
[0x00000000, 0x11111111, 0x22222222, 0x33333333],
2109+
[0xCCCCCCCC, 0x22222222, 0xDDDDDDDD, 0x33333333]
2110+
}
19692111
}

0 commit comments

Comments
 (0)