diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 1060f911a9ed4..b309a124e8089 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -918,12 +918,29 @@ fn generic_simd_intrinsic(
}
if let Some(stripped) = name_str.strip_prefix("simd_shuffle") {
- let n: u64 = stripped.parse().unwrap_or_else(|_| {
- span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
- });
+ // If this intrinsic is the older "simd_shuffleN" form, simply parse the integer.
+ // If there is no suffix, use the index array length.
+ let n: u64 = if stripped.is_empty() {
+ // Make sure this is actually an array, since typeck only checks the length-suffixed
+ // version of this intrinsic.
+ match args[2].layout.ty.kind() {
+ ty::Array(ty, len) if matches!(ty.kind(), ty::Uint(ty::UintTy::U32)) => {
+ len.try_eval_usize(bx.cx.tcx, ty::ParamEnv::reveal_all()).unwrap_or_else(|| {
+ span_bug!(span, "could not evaluate shuffle index array length")
+ })
+ }
+ _ => return_error!(
+ "simd_shuffle index must be an array of `u32`, got `{}`",
+ args[2].layout.ty
+ ),
+ }
+ } else {
+ stripped.parse().unwrap_or_else(|_| {
+ span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
+ })
+ };
require_simd!(ret_ty, "return");
-
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!(
out_len == n,
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index cd0e9354c2441..0861aab2e318c 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -665,8 +665,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
if i == 2 && intrinsic.as_str().starts_with("simd_shuffle") {
if let mir::Operand::Constant(constant) = arg {
let c = self.eval_mir_constant(constant);
- let (llval, ty) =
- self.simd_shuffle_indices(&bx, constant.span, constant.ty(), c);
+ let (llval, ty) = self.simd_shuffle_indices(
+ &bx,
+ constant.span,
+ self.monomorphize(constant.ty()),
+ c,
+ );
return OperandRef {
val: Immediate(llval),
layout: bx.layout_of(ty),
diff --git a/compiler/rustc_error_codes/src/error_codes/E0439.md b/compiler/rustc_error_codes/src/error_codes/E0439.md
index 3e663df866caa..24268aef2222a 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0439.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0439.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
The length of the platform-intrinsic function `simd_shuffle` wasn't specified.
Erroneous code example:
-```compile_fail,E0439
+```ignore (no longer emitted)
#![feature(platform_intrinsics)]
extern "platform-intrinsic" {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 78846d8ffb26b..322bea3806cfa 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1212,6 +1212,7 @@ symbols! {
simd_select_bitmask,
simd_shl,
simd_shr,
+ simd_shuffle,
simd_sub,
simd_trunc,
simd_xor,
diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs
index 664954b0eb7a2..ff7a26853b188 100644
--- a/compiler/rustc_typeck/src/check/intrinsic.rs
+++ b/compiler/rustc_typeck/src/check/intrinsic.rs
@@ -2,7 +2,7 @@
//! intrinsics that the compiler exposes.
use crate::errors::{
- SimdShuffleMissingLength, UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
+ UnrecognizedAtomicOperation, UnrecognizedIntrinsicFunction,
WrongNumberOfGenericArgumentsToIntrinsic,
};
use crate::require_same_types;
@@ -468,6 +468,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
| sym::simd_reduce_max
| sym::simd_reduce_min_nanless
| sym::simd_reduce_max_nanless => (2, vec![param(0)], param(1)),
+ sym::simd_shuffle => (3, vec![param(0), param(0), param(1)], param(2)),
name if name.as_str().starts_with("simd_shuffle") => {
match name.as_str()["simd_shuffle".len()..].parse() {
Ok(n) => {
@@ -475,7 +476,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
(2, params, param(1))
}
Err(_) => {
- tcx.sess.emit_err(SimdShuffleMissingLength { span: it.span, name });
+ let msg =
+ format!("unrecognized platform-specific intrinsic function: `{}`", name);
+ tcx.sess.struct_span_err(it.span, &msg).emit();
return;
}
}
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs
index 1e6a240b2f86d..47077779616c0 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_typeck/src/errors.rs
@@ -121,14 +121,6 @@ pub struct AssocTypeBindingNotAllowed {
pub span: Span,
}
-#[derive(SessionDiagnostic)]
-#[error = "E0439"]
-pub struct SimdShuffleMissingLength {
- #[message = "invalid `simd_shuffle`, needs length: `{name}`"]
- pub span: Span,
- pub name: Symbol,
-}
-
#[derive(SessionDiagnostic)]
#[error = "E0436"]
pub struct FunctionalRecordUpdateOnNonStruct {
diff --git a/src/test/ui/error-codes/E0439.rs b/src/test/ui/error-codes/E0439.rs
deleted file mode 100644
index 86e9cb55a9c86..0000000000000
--- a/src/test/ui/error-codes/E0439.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-#![feature(platform_intrinsics)]
-
-extern "platform-intrinsic" {
- fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B; //~ ERROR E0439
-}
-
-fn main () {
-}
diff --git a/src/test/ui/error-codes/E0439.stderr b/src/test/ui/error-codes/E0439.stderr
deleted file mode 100644
index 8021f7d3951a8..0000000000000
--- a/src/test/ui/error-codes/E0439.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0439]: invalid `simd_shuffle`, needs length: `simd_shuffle`
- --> $DIR/E0439.rs:4:5
- |
-LL | fn simd_shuffle(a: A, b: A, c: [u32; 8]) -> B;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0439`.
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs
new file mode 100644
index 0000000000000..9611780ac079e
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.rs
@@ -0,0 +1,33 @@
+// build-fail
+
+// Test that the simd_shuffle intrinsic produces ok-ish error
+// messages when misused.
+
+#![feature(repr_simd, platform_intrinsics)]
+
+#[repr(simd)]
+#[derive(Copy, Clone)]
+pub struct Simd([T; N]);
+
+extern "platform-intrinsic" {
+ fn simd_shuffle(a: T, b: T, i: I) -> U;
+}
+
+fn main() {
+ const I: [u32; 2] = [0; 2];
+ const I2: [f32; 2] = [0.; 2];
+ let v = Simd::([0; 4]);
+
+ unsafe {
+ let _: Simd = simd_shuffle(v, v, I);
+
+ let _: Simd = simd_shuffle(v, v, I);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+
+ let _: Simd = simd_shuffle(v, v, I);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+
+ let _: Simd = simd_shuffle(v, v, I2);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+ }
+}
diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr
new file mode 100644
index 0000000000000..9eeb000fd261f
--- /dev/null
+++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-shuffle.stderr
@@ -0,0 +1,21 @@
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `Simd` with length 4
+ --> $DIR/simd-intrinsic-generic-shuffle.rs:24:31
+ |
+LL | let _: Simd = simd_shuffle(v, v, I);
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `u32` (element of input `Simd`), found `Simd` with element type `f32`
+ --> $DIR/simd-intrinsic-generic-shuffle.rs:27:31
+ |
+LL | let _: Simd = simd_shuffle(v, v, I);
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: simd_shuffle index must be an array of `u32`, got `[f32; 2]`
+ --> $DIR/simd-intrinsic-generic-shuffle.rs:30:31
+ |
+LL | let _: Simd = simd_shuffle(v, v, I2);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd/monomorphize-shuffle-index.rs b/src/test/ui/simd/monomorphize-shuffle-index.rs
new file mode 100644
index 0000000000000..2467baa08b0a7
--- /dev/null
+++ b/src/test/ui/simd/monomorphize-shuffle-index.rs
@@ -0,0 +1,40 @@
+//run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+ fn simd_shuffle(a: T, b: T, i: I) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd([T; N]);
+
+trait Shuffle {
+ const I: [u32; N];
+
+ unsafe fn shuffle(&self, a: Simd, b: Simd) -> Simd {
+ simd_shuffle(a, b, Self::I)
+ }
+}
+
+fn main() {
+ struct I1;
+ impl Shuffle<4> for I1 {
+ const I: [u32; 4] = [0, 2, 4, 6];
+ }
+
+ struct I2;
+ impl Shuffle<2> for I2 {
+ const I: [u32; 2] = [1, 5];
+ }
+
+ let a = Simd::([0, 1, 2, 3]);
+ let b = Simd::([4, 5, 6, 7]);
+ unsafe {
+ let x: Simd = I1.shuffle(a, b);
+ assert_eq!(x.0, [0, 2, 4, 6]);
+
+ let y: Simd = I2.shuffle(a, b);
+ assert_eq!(y.0, [1, 5]);
+ }
+}
diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.rs b/src/test/ui/simd/shuffle-not-out-of-bounds.rs
index 8a533453e75fd..aae6ce4663fba 100644
--- a/src/test/ui/simd/shuffle-not-out-of-bounds.rs
+++ b/src/test/ui/simd/shuffle-not-out-of-bounds.rs
@@ -188,4 +188,14 @@ fn main() {
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
+
+ extern "platform-intrinsic" {
+ fn simd_shuffle(a: T, b: T, i: I) -> U;
+ }
+ let v = u8x2(0, 0);
+ const I: [u32; 2] = [4, 4];
+ unsafe {
+ let _: u8x2 = simd_shuffle(v, v, I);
+ //~^ ERROR invalid monomorphization of `simd_shuffle` intrinsic
+ }
}
diff --git a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr
index 07253a4ae46bc..737fb5e6e51e2 100644
--- a/src/test/ui/simd/shuffle-not-out-of-bounds.stderr
+++ b/src/test/ui/simd/shuffle-not-out-of-bounds.stderr
@@ -71,6 +71,12 @@ LL | | 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1));
|
= note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: aborting due to 6 previous errors
+error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: shuffle index #0 is out of bounds (limit 4)
+ --> $DIR/shuffle-not-out-of-bounds.rs:198:23
+ |
+LL | let _: u8x2 = simd_shuffle(v, v, I);
+ | ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0511`.
diff --git a/src/test/ui/simd/shuffle.rs b/src/test/ui/simd/shuffle.rs
new file mode 100644
index 0000000000000..3592adfdc6ad1
--- /dev/null
+++ b/src/test/ui/simd/shuffle.rs
@@ -0,0 +1,24 @@
+//run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+ fn simd_shuffle(a: T, b: T, i: I) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd([T; N]);
+
+fn main() {
+ const I1: [u32; 4] = [0, 2, 4, 6];
+ const I2: [u32; 2] = [1, 5];
+ let a = Simd::([0, 1, 2, 3]);
+ let b = Simd::([4, 5, 6, 7]);
+ unsafe {
+ let x: Simd = simd_shuffle(a, b, I1);
+ assert_eq!(x.0, [0, 2, 4, 6]);
+
+ let y: Simd = simd_shuffle(a, b, I2);
+ assert_eq!(y.0, [1, 5]);
+ }
+}