Skip to content

Commit 194baa8

Browse files
committed
simd_shuffle intrinsic: allow argument to be passed as vector (not just as array)
1 parent e9e27ab commit 194baa8

File tree

5 files changed

+60
-17
lines changed

5 files changed

+60
-17
lines changed

compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,14 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
191191
})
192192
.try_into()
193193
.unwrap(),
194+
_ if idx_ty.is_simd()
195+
&& matches!(
196+
idx_ty.simd_size_and_type(fx.tcx).1.kind(),
197+
ty::Uint(ty::UintTy::U32)
198+
) =>
199+
{
200+
idx_ty.simd_size_and_type(fx.tcx).0.try_into().unwrap()
201+
}
194202
_ => {
195203
fx.tcx.dcx().span_err(
196204
span,
@@ -213,6 +221,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
213221

214222
let total_len = lane_count * 2;
215223

224+
// FIXME: this is a terrible abstraction-breaking hack.
225+
// Find a way to reuse `immediate_const_vector` from `codegen_ssa` instead.
216226
let indexes = {
217227
use rustc_middle::mir::interpret::*;
218228
let idx_const = match &idx.node {

compiler/rustc_codegen_gcc/src/intrinsic/simd.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -353,19 +353,24 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
353353
}
354354

355355
if name == sym::simd_shuffle {
356-
// Make sure this is actually an array, since typeck only checks the length-suffixed
356+
// Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed
357357
// version of this intrinsic.
358-
let n: u64 = match *args[2].layout.ty.kind() {
358+
let idx_ty = args[2].layout.ty;
359+
let n: u64 = match idx_ty.kind() {
359360
ty::Array(ty, len) if matches!(*ty.kind(), ty::Uint(ty::UintTy::U32)) => {
360361
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
361362
|| span_bug!(span, "could not evaluate shuffle index array length"),
362363
)
363364
}
364-
_ => return_error!(InvalidMonomorphization::SimdShuffle {
365-
span,
366-
name,
367-
ty: args[2].layout.ty
368-
}),
365+
_ if idx_ty.is_simd()
366+
&& matches!(
367+
idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(),
368+
ty::Uint(ty::UintTy::U32)
369+
) =>
370+
{
371+
idx_ty.simd_size_and_type(bx.cx.tcx).0
372+
}
373+
_ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }),
369374
};
370375
require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
371376

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,19 +1279,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
12791279
}
12801280

12811281
if name == sym::simd_shuffle {
1282-
// Make sure this is actually an array, since typeck only checks the length-suffixed
1282+
// Make sure this is actually an array or SIMD vector, since typeck only checks the length-suffixed
12831283
// version of this intrinsic.
1284-
let n: u64 = match args[2].layout.ty.kind() {
1284+
let idx_ty = args[2].layout.ty;
1285+
let n: u64 = match idx_ty.kind() {
12851286
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
12861287
len.try_eval_target_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(
12871288
|| span_bug!(span, "could not evaluate shuffle index array length"),
12881289
)
12891290
}
1290-
_ => return_error!(InvalidMonomorphization::SimdShuffle {
1291-
span,
1292-
name,
1293-
ty: args[2].layout.ty
1294-
}),
1291+
_ if idx_ty.is_simd()
1292+
&& matches!(
1293+
idx_ty.simd_size_and_type(bx.cx.tcx).1.kind(),
1294+
ty::Uint(ty::UintTy::U32)
1295+
) =>
1296+
{
1297+
idx_ty.simd_size_and_type(bx.cx.tcx).0
1298+
}
1299+
_ => return_error!(InvalidMonomorphization::SimdShuffle { span, name, ty: idx_ty }),
12951300
};
12961301

12971302
let (out_len, out_ty) = require_simd!(ret_ty, SimdReturn);

library/core/src/intrinsics/simd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ extern "rust-intrinsic" {
232232
///
233233
/// `T` must be a vector.
234234
///
235-
/// `U` must be a **const** array of `i32`s. This means it must either refer to a named
235+
/// `U` must be a **const** array or vector of `u32`s. This means it must either refer to a named
236236
/// const or be given as an inline const expression (`const { ... }`).
237237
///
238238
/// `V` must be a vector with the same element type as `T` and the same length as `U`.

tests/ui/simd/shuffle.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,20 @@
66
#![allow(incomplete_features)]
77
#![feature(adt_const_params)]
88

9+
use std::marker::ConstParamTy;
10+
911
extern "rust-intrinsic" {
1012
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
1113
}
1214

13-
#[derive(Copy, Clone)]
15+
#[derive(Copy, Clone, ConstParamTy, PartialEq, Eq)]
1416
#[repr(simd)]
1517
struct Simd<T, const N: usize>([T; N]);
1618

17-
pub unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U {
19+
unsafe fn __shuffle_vector16<const IDX: [u32; 16], T, U>(x: T, y: T) -> U {
20+
simd_shuffle(x, y, IDX)
21+
}
22+
unsafe fn __shuffle_vector16_v2<const IDX: Simd<u32, 16>, T, U>(x: T, y: T) -> U {
1823
simd_shuffle(x, y, IDX)
1924
}
2025

@@ -30,6 +35,17 @@ fn main() {
3035
let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
3136
assert_eq!(y.0, [1, 5]);
3237
}
38+
// Test that we can also use a SIMD vector instead of a normal array for the shuffle.
39+
const I1_SIMD: Simd<u32, 4> = Simd([0, 2, 4, 6]);
40+
const I2_SIMD: Simd<u32, 2> = Simd([1, 5]);
41+
unsafe {
42+
let x: Simd<u8, 4> = simd_shuffle(a, b, I1_SIMD);
43+
assert_eq!(x.0, [0, 2, 4, 6]);
44+
45+
let y: Simd<u8, 2> = simd_shuffle(a, b, I2_SIMD);
46+
assert_eq!(y.0, [1, 5]);
47+
}
48+
3349
// Test that an indirection (via an unnamed constant)
3450
// through a const generic parameter also works.
3551
// See https://github.com/rust-lang/rust/issues/113500 for details.
@@ -42,4 +58,11 @@ fn main() {
4258
Simd<u8, 16>,
4359
>(a, b);
4460
}
61+
unsafe {
62+
__shuffle_vector16_v2::<
63+
{ Simd([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) },
64+
Simd<u8, 16>,
65+
Simd<u8, 16>,
66+
>(a, b);
67+
}
4568
}

0 commit comments

Comments
 (0)