Skip to content

Commit e675073

Browse files
authored
Rollup merge of #88855 - calebzulawski:feature/simd_shuffle, r=nagisa
Allow simd_shuffle to accept vectors of any length cc ``@rust-lang/project-portable-simd`` ``@workingjubilee``
2 parents ebd31f5 + 4a4ca94 commit e675073

File tree

14 files changed

+171
-35
lines changed

14 files changed

+171
-35
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -918,12 +918,29 @@ fn generic_simd_intrinsic(
918918
}
919919

920920
if let Some(stripped) = name_str.strip_prefix("simd_shuffle") {
921-
let n: u64 = stripped.parse().unwrap_or_else(|_| {
922-
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
923-
});
921+
// If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
922+
// If there is no suffix, use the index array length.
923+
let n: u64 = if stripped.is_empty() {
924+
// Make sure this is actually an array, since typeck only checks the length-suffixed
925+
// version of this intrinsic.
926+
match args[2].layout.ty.kind() {
927+
ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
928+
len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| {
929+
span_bug!(span, "could not evaluate shuffle index array length")
930+
})
931+
}
932+
_ => return_error!(
933+
"simd_shuffle index must be an array of `u32`, got `{}`",
934+
args[2].layout.ty
935+
),
936+
}
937+
} else {
938+
stripped.parse().unwrap_or_else(|_| {
939+
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
940+
})
941+
};
924942

925943
require_simd!(ret_ty, "return");
926-
927944
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
928945
require!(
929946
out_len == n,

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
665665
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
666666
if let mir::Operand::Constant(constant) = arg {
667667
let c = self.eval_mir_constant(constant);
668-
let (llval, ty) =
669-
self.simd_shuffle_indices(&bx, constant.span, constant.ty(), c);
668+
let (llval, ty) = self.simd_shuffle_indices(
669+
&bx,
670+
constant.span,
671+
self.monomorphize(constant.ty()),
672+
c,
673+
);
670674
return OperandRef {
671675
val: Immediate(llval),
672676
layout: bx.layout_of(ty),

compiler/rustc_error_codes/src/error_codes/E0439.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
The length of the platform-intrinsic function `simd_shuffle` wasn't specified.
24

35
Erroneous code example:
46

5-
```compile_fail,E0439
7+
```ignore (no longer emitted)
68
#![feature(platform_intrinsics)]
79
810
extern "platform-intrinsic" {

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,7 @@ symbols! {
12121212
simd_select_bitmask,
12131213
simd_shl,
12141214
simd_shr,
1215+
simd_shuffle,
12151216
simd_sub,
12161217
simd_trunc,
12171218
simd_xor,

compiler/rustc_typeck/src/check/intrinsic.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! intrinsics that the compiler exposes.
33
44
use crate::errors::{
5-
SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
5+
UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
66
WrongNumberOfGenericArgumentsToIntrinsic,
77
};
88
use crate::require_same_types;
@@ -468,14 +468,17 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
468468
| sym::simd_reduce_max
469469
| sym::simd_reduce_min_nanless
470470
| sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
471+
sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
471472
name if name.as_str().starts_with("simd_shuffle") => {
472473
match name.as_str()["simd_shuffle".len()..].parse() {
473474
Ok(n) => {
474475
let params = vec![param(0), param(0), tcx.mk_array(tcx.types.u32, n)];
475476
(2, params, param(1))
476477
}
477478
Err(_) => {
478-
tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name });
479+
let msg =
480+
format!("unrecognized platform-specific intrinsic function: `{}`", name);
481+
tcx.sess.struct_span_err(it.span, &msg).emit();
479482
return;
480483
}
481484
}

compiler/rustc_typeck/src/errors.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,6 @@ pub struct AssocTypeBindingNotAllowed {
121121
pub span: Span,
122122
}
123123

124-
#[derive(SessionDiagnostic)]
125-
#[error = "E0439"]
126-
pub struct SimdShuffleMissingLength {
127-
#[message = "invalid `simd_shuffle`, needs length: `{name}`"]
128-
pub span: Span,
129-
pub name: Symbol,
130-
}
131-
132124
#[derive(SessionDiagnostic)]
133125
#[error = "E0436"]
134126
pub struct FunctionalRecordUpdateOnNonStruct {

src/test/ui/error-codes/E0439.rs

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/test/ui/error-codes/E0439.stderr

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// build-fail
2+
3+
// Test that the simd_shuffle intrinsic produces ok-ish error
4+
// messages when misused.
5+
6+
#![feature(repr_simd, platform_intrinsics)]
7+
8+
#[repr(simd)]
9+
#[derive(Copy, Clone)]
10+
pub struct Simd<T, const N: usize>([T; N]);
11+
12+
extern "platform-intrinsic" {
13+
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
14+
}
15+
16+
fn main() {
17+
const I: [u32; 2] = [0; 2];
18+
const I2: [f32; 2] = [0.; 2];
19+
let v = Simd::<u32, 4>([0; 4]);
20+
21+
unsafe {
22+
let _: Simd<u32, 2> = simd_shuffle(v, v, I);
23+
24+
let _: Simd<u32, 4> = simd_shuffle(v, v, I);
25+
//~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
26+
27+
let _: Simd<f32, 2> = simd_shuffle(v, v, I);
28+
//~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
29+
30+
let _: Simd<u32, 2> = simd_shuffle(v, v, I2);
31+
//~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
32+
}
33+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd<u32, 4_usize>` with length 4
2+
--> $DIR/simd-intrinsic-generic-shuffle.rs:24:31
3+
|
4+
LL | let _: Simd<u32, 4> = simd_shuffle(v, v, I);
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
7+
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd<u32, 4_usize>`), found `Simd<f32, 2_usize>` with element type `f32`
8+
--> $DIR/simd-intrinsic-generic-shuffle.rs:27:31
9+
|
10+
LL | let _: Simd<f32, 2> = simd_shuffle(v, v, I);
11+
| ^^^^^^^^^^^^^^^^^^^^^
12+
13+
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]`
14+
--> $DIR/simd-intrinsic-generic-shuffle.rs:30:31
15+
|
16+
LL | let _: Simd<u32, 2> = simd_shuffle(v, v, I2);
17+
| ^^^^^^^^^^^^^^^^^^^^^^
18+
19+
error: aborting due to 3 previous errors
20+
21+
For more information about this error, try `rustc --explain E0511`.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//run-pass
2+
#![feature(repr_simd, platform_intrinsics)]
3+
4+
extern "platform-intrinsic" {
5+
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
6+
}
7+
8+
#[derive(Copy, Clone)]
9+
#[repr(simd)]
10+
struct Simd<T, const N: usize>([T; N]);
11+
12+
trait Shuffle<const N: usize> {
13+
const I: [u32; N];
14+
15+
unsafe fn shuffle<T, const M: usize>(&self, a: Simd<T, M>, b: Simd<T, M>) -> Simd<T, N> {
16+
simd_shuffle(a, b, Self::I)
17+
}
18+
}
19+
20+
fn main() {
21+
struct I1;
22+
impl Shuffle<4> for I1 {
23+
const I: [u32; 4] = [0, 2, 4, 6];
24+
}
25+
26+
struct I2;
27+
impl Shuffle<2> for I2 {
28+
const I: [u32; 2] = [1, 5];
29+
}
30+
31+
let a = Simd::<u8, 4>([0, 1, 2, 3]);
32+
let b = Simd::<u8, 4>([4, 5, 6, 7]);
33+
unsafe {
34+
let x: Simd<u8, 4> = I1.shuffle(a, b);
35+
assert_eq!(x.0, [0, 2, 4, 6]);
36+
37+
let y: Simd<u8, 2> = I2.shuffle(a, b);
38+
assert_eq!(y.0, [1, 5]);
39+
}
40+
}

src/test/ui/simd/shuffle-not-out-of-bounds.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,4 +188,14 @@ fn main() {
188188
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
189189
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
190190
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
191+
192+
extern "platform-intrinsic" {
193+
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
194+
}
195+
let v = u8x2(0, 0);
196+
const I: [u32; 2] = [4, 4];
197+
unsafe {
198+
let _: u8x2 = simd_shuffle(v, v, I);
199+
//~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
200+
}
191201
}

src/test/ui/simd/shuffle-not-out-of-bounds.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ LL | | 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
7171
|
7272
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
7373

74-
error: aborting due to 6 previous errors
74+
error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
75+
--> $DIR/shuffle-not-out-of-bounds.rs:198:23
76+
|
77+
LL | let _: u8x2 = simd_shuffle(v, v, I);
78+
| ^^^^^^^^^^^^^^^^^^^^^
79+
80+
error: aborting due to 7 previous errors
7581

7682
For more information about this error, try `rustc --explain E0511`.

src/test/ui/simd/shuffle.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//run-pass
2+
#![feature(repr_simd, platform_intrinsics)]
3+
4+
extern "platform-intrinsic" {
5+
fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
6+
}
7+
8+
#[derive(Copy, Clone)]
9+
#[repr(simd)]
10+
struct Simd<T, const N: usize>([T; N]);
11+
12+
fn main() {
13+
const I1: [u32; 4] = [0, 2, 4, 6];
14+
const I2: [u32; 2] = [1, 5];
15+
let a = Simd::<u8, 4>([0, 1, 2, 3]);
16+
let b = Simd::<u8, 4>([4, 5, 6, 7]);
17+
unsafe {
18+
let x: Simd<u8, 4> = simd_shuffle(a, b, I1);
19+
assert_eq!(x.0, [0, 2, 4, 6]);
20+
21+
let y: Simd<u8, 2> = simd_shuffle(a, b, I2);
22+
assert_eq!(y.0, [1, 5]);
23+
}
24+
}

0 commit comments

Comments
 (0)