From 4a4ca941515399694227d720ece032e299470c91 Mon Sep 17 00:00:00 2001
From: Caleb Zulawski <caleb.zulawski@gmail.com>
Date: Thu, 16 Sep 2021 02:59:49 +0000
Subject: [PATCH] Fix shuffle index constant not being monomorphized.

---
 compiler/rustc_codegen_ssa/src/mir/block.rs   |  8 +++-
 .../ui/simd/monomorphize-shuffle-index.rs     | 40 +++++++++++++++++++
 2 files changed, 46 insertions(+), 2 deletions(-)
 create mode 100644 src/test/ui/simd/monomorphize-shuffle-index.rs

diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 2ca7e8fd7e8..c7c577e6c78 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/src/test/ui/simd/monomorphize-shuffle-index.rs b/src/test/ui/simd/monomorphize-shuffle-index.rs
new file mode 100644
index 00000000000..2467baa08b0
--- /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<T, I, U>(a: T, b: T, i: I) -> U;
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+trait Shuffle<const N: usize> {
+    const I: [u32; N];
+
+    unsafe fn shuffle<T, const M: usize>(&self, a: Simd<T, M>, b: Simd<T, M>) -> Simd<T, N> {
+        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::<u8, 4>([0, 1, 2, 3]);
+    let b = Simd::<u8, 4>([4, 5, 6, 7]);
+    unsafe {
+        let x: Simd<u8, 4> = I1.shuffle(a, b);
+        assert_eq!(x.0, [0, 2, 4, 6]);
+
+        let y: Simd<u8, 2> = I2.shuffle(a, b);
+        assert_eq!(y.0, [1, 5]);
+    }
+}