about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--.mailmap2
-rw-r--r--.reuse/dep51
-rw-r--r--Cargo.lock18
-rw-r--r--compiler/rustc_arena/src/lib.rs124
-rw-r--r--compiler/rustc_ast/src/entry.rs27
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs22
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs50
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs57
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs6
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_hir/src/lang_items.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs44
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs67
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs7
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs110
-rw-r--r--compiler/rustc_passes/src/entry.rs33
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs39
-rw-r--r--compiler/rustc_span/src/symbol.rs3
-rw-r--r--compiler/stable_mir/src/fold.rs25
-rw-r--r--compiler/stable_mir/src/ty.rs46
-rw-r--r--compiler/stable_mir/src/visitor.rs20
-rw-r--r--library/alloc/src/sync.rs8
-rw-r--r--library/core/src/mem/mod.rs2
-rw-r--r--library/core/src/panic.rs45
-rw-r--r--library/core/src/panicking.rs12
-rw-r--r--library/core/src/sync/exclusive.rs46
-rw-r--r--library/std/src/time.rs2
-rw-r--r--rust-bors.toml1
-rw-r--r--src/bootstrap/bootstrap.py6
-rw-r--r--src/bootstrap/install.rs31
-rw-r--r--src/bootstrap/mk/Makefile.in7
-rw-r--r--src/ci/docker/README.md4
-rw-r--r--src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile5
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile3
-rw-r--r--src/ci/docker/scripts/crosstool-ng-git.sh17
-rw-r--r--src/ci/docker/scripts/crosstool-ng.sh2
-rw-r--r--src/ci/github-actions/ci.yml2
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/doc/rustc/src/platform-support/loongarch-none.md2
-rw-r--r--src/doc/unstable-book/src/language-features/plugin.md2
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/clean/types.rs35
-rw-r--r--src/tools/build-manifest/src/main.rs2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs23
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs16
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/mod.rs32
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs20
-rw-r--r--src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr16
-rw-r--r--src/tools/compiletest/src/common.rs6
-rw-r--r--src/tools/compiletest/src/header/needs.rs5
-rw-r--r--src/tools/miri/Cargo.lock10
-rw-r--r--src/tools/miri/Cargo.toml2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs9
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs39
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs53
-rw-r--r--src/tools/miri/src/shims/x86/sse2.rs36
-rw-r--r--src/tools/miri/src/shims/x86/sse3.rs90
-rw-r--r--src/tools/miri/src/shims/x86/ssse3.rs199
-rw-r--r--src/tools/miri/tests/pass/float.rs10
-rw-r--r--src/tools/miri/tests/pass/intrinsics-math.rs27
-rw-r--r--src/tools/miri/tests/pass/intrinsics-x86-sse2.rs18
-rw-r--r--src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs395
-rw-r--r--src/tools/miri/tests/pass/portable-simd.rs15
-rw-r--r--src/version2
-rw-r--r--tests/coverage-map/unreachable.cov-map24
-rw-r--r--tests/coverage-map/unreachable.rs37
-rw-r--r--tests/incremental/change_crate_dep_kind.rs1
-rw-r--r--tests/run-coverage/unreachable.coverage38
-rw-r--r--tests/run-coverage/unreachable.rs37
-rw-r--r--tests/ui/abi/compatibility.rs183
-rw-r--r--tests/ui/abi/relocation_model_pic.rs3
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.rs1
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr2
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.rs1
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.run.stderr2
-rw-r--r--tests/ui/resolve/issue-116164.rs19
-rw-r--r--tests/ui/resolve/issue-116164.stderr14
-rw-r--r--tests/ui/simd/intrinsic/generic-elements.rs28
-rw-r--r--tests/ui/simd/intrinsic/generic-elements.stderr80
-rw-r--r--tests/ui/simd/monomorphize-shuffle-index.generic.stderr12
-rw-r--r--tests/ui/simd/monomorphize-shuffle-index.rs28
-rw-r--r--tests/ui/suggestions/auxiliary/extern-issue-98562.rs26
-rw-r--r--tests/ui/suggestions/issue-98562.rs12
-rw-r--r--tests/ui/suggestions/issue-98562.stderr11
-rw-r--r--tests/ui/suggestions/missing-assoc-fn.stderr2
-rwxr-xr-xx2
93 files changed, 2133 insertions, 421 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4dcc9556965..624608cc477 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -542,7 +542,7 @@ jobs:
       ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
       AWS_REGION: us-west-1
       CACHE_DOMAIN: ci-caches.rust-lang.org
-    if: "github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
+    if: "github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))"
     strategy:
       matrix:
         include:
diff --git a/.mailmap b/.mailmap
index 21e1adb43cf..26d6be9f0c6 100644
--- a/.mailmap
+++ b/.mailmap
@@ -429,6 +429,8 @@ Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> nils <48135649+Nilstrieb
 Nif Ward <nif.ward@gmail.com>
 Nika Layzell <nika@thelayzells.com> <michael@thelayzells.com>
 NODA Kai <nodakai@gmail.com>
+Oğuz Ağcayazı <oguz.agcayazi@gmail.com> <oguz.agcayazi@gmail.com>
+Oğuz Ağcayazı <oguz.agcayazi@gmail.com> <ouz.agz@gmail.com>
 oliver <16816606+o752d@users.noreply.github.com>
 Oliver Middleton <olliemail27@gmail.com> <ollie27@users.noreply.github.com>
 Oliver Scherer <oli-obk@users.noreply.github.com> <git-spam-no-reply9815368754983@oli-obk.de>
diff --git a/.reuse/dep5 b/.reuse/dep5
index 5546a7cf391..245ed2659f9 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -25,6 +25,7 @@ Files: compiler/*
        README.md
        RELEASES.md
        rustfmt.toml
+       rust-bors.toml
        triagebot.toml
        x
        x.ps1
diff --git a/Cargo.lock b/Cargo.lock
index 476f5578187..7f91d12a419 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2137,6 +2137,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "libloading"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
+dependencies = [
+ "cfg-if",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "libm"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2411,7 +2421,7 @@ dependencies = [
  "lazy_static",
  "libc",
  "libffi",
- "libloading",
+ "libloading 0.8.1",
  "log",
  "measureme",
  "rand",
@@ -3914,7 +3924,7 @@ dependencies = [
 name = "rustc_interface"
 version = "0.0.0"
 dependencies = [
- "libloading",
+ "libloading 0.7.4",
  "rustc-rayon",
  "rustc-rayon-core",
  "rustc_ast",
@@ -4045,7 +4055,7 @@ name = "rustc_metadata"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.3.2",
- "libloading",
+ "libloading 0.7.4",
  "odht",
  "rustc_ast",
  "rustc_attr",
@@ -4260,7 +4270,7 @@ dependencies = [
 name = "rustc_plugin_impl"
 version = "0.0.0"
 dependencies = [
- "libloading",
+ "libloading 0.7.4",
  "rustc_ast",
  "rustc_errors",
  "rustc_fluent_macro",
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 23fdd272ffd..06eb8a185be 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -172,8 +172,8 @@ impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> {
             return &mut [];
         }
         // Move the content to the arena by copying and then forgetting it.
+        let start_ptr = arena.alloc_raw_slice(len);
         unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
             self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
             mem::forget(self);
             slice::from_raw_parts_mut(start_ptr, len)
@@ -189,8 +189,8 @@ impl<T> IterExt<T> for Vec<T> {
             return &mut [];
         }
         // Move the content to the arena by copying and then forgetting it.
+        let start_ptr = arena.alloc_raw_slice(len);
         unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
             self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
             self.set_len(0);
             slice::from_raw_parts_mut(start_ptr, len)
@@ -206,8 +206,8 @@ impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> {
             return &mut [];
         }
         // Move the content to the arena by copying and then forgetting it.
+        let start_ptr = arena.alloc_raw_slice(len);
         unsafe {
-            let start_ptr = arena.alloc_raw_slice(len);
             self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
             self.set_len(0);
             slice::from_raw_parts_mut(start_ptr, len)
@@ -250,25 +250,20 @@ impl<T> TypedArena<T> {
         available_bytes >= additional_bytes
     }
 
-    /// Ensures there's enough space in the current chunk to fit `len` objects.
     #[inline]
-    fn ensure_capacity(&self, additional: usize) {
-        if !self.can_allocate(additional) {
-            self.grow(additional);
-            debug_assert!(self.can_allocate(additional));
-        }
-    }
-
-    #[inline]
-    unsafe fn alloc_raw_slice(&self, len: usize) -> *mut T {
+    fn alloc_raw_slice(&self, len: usize) -> *mut T {
         assert!(mem::size_of::<T>() != 0);
         assert!(len != 0);
 
-        self.ensure_capacity(len);
+        // Ensure the current chunk can fit `len` objects.
+        if !self.can_allocate(len) {
+            self.grow(len);
+            debug_assert!(self.can_allocate(len));
+        }
 
         let start_ptr = self.ptr.get();
-        // SAFETY: `self.ensure_capacity` makes sure that there is enough space
-        // for `len` elements.
+        // SAFETY: `can_allocate`/`grow` ensures that there is enough space for
+        // `len` elements.
         unsafe { self.ptr.set(start_ptr.add(len)) };
         start_ptr
     }
@@ -407,6 +402,8 @@ impl Default for DroplessArena {
     #[inline]
     fn default() -> DroplessArena {
         DroplessArena {
+            // We set both `start` and `end` to 0 so that the first call to
+            // alloc() will trigger a grow().
             start: Cell::new(ptr::null_mut()),
             end: Cell::new(ptr::null_mut()),
             chunks: Default::default(),
@@ -415,9 +412,11 @@ impl Default for DroplessArena {
 }
 
 impl DroplessArena {
+    #[inline(never)]
+    #[cold]
     fn grow(&self, layout: Layout) {
         // Add some padding so we can align `self.end` while
-        // stilling fitting in a `layout` allocation.
+        // still fitting in a `layout` allocation.
         let additional = layout.size() + cmp::max(DROPLESS_ALIGNMENT, layout.align()) - 1;
 
         unsafe {
@@ -441,7 +440,7 @@ impl DroplessArena {
             let mut chunk = ArenaChunk::new(align_up(new_cap, PAGE));
             self.start.set(chunk.start());
 
-            // Align the end to DROPLESS_ALIGNMENT
+            // Align the end to DROPLESS_ALIGNMENT.
             let end = align_down(chunk.end().addr(), DROPLESS_ALIGNMENT);
 
             // Make sure we don't go past `start`. This should not happen since the allocation
@@ -454,55 +453,40 @@ impl DroplessArena {
         }
     }
 
-    #[inline(never)]
-    #[cold]
-    fn grow_and_alloc_raw(&self, layout: Layout) -> *mut u8 {
-        self.grow(layout);
-        self.alloc_raw_without_grow(layout).unwrap()
-    }
-
-    #[inline(never)]
-    #[cold]
-    fn grow_and_alloc<T>(&self) -> *mut u8 {
-        self.grow_and_alloc_raw(Layout::new::<T>())
-    }
-
-    /// Allocates a byte slice with specified layout from the current memory
-    /// chunk. Returns `None` if there is no free space left to satisfy the
-    /// request.
-    #[inline]
-    fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> {
-        let start = self.start.get().addr();
-        let old_end = self.end.get();
-        let end = old_end.addr();
-
-        // Align allocated bytes so that `self.end` stays aligned to DROPLESS_ALIGNMENT
-        let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT);
-
-        // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT
-        unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) };
-
-        let new_end = align_down(end.checked_sub(bytes)?, layout.align());
-        if start <= new_end {
-            let new_end = old_end.with_addr(new_end);
-            // `new_end` is aligned to DROPLESS_ALIGNMENT as `align_down` preserves alignment
-            // as both `end` and `bytes` are already aligned to DROPLESS_ALIGNMENT.
-            self.end.set(new_end);
-            Some(new_end)
-        } else {
-            None
-        }
-    }
-
     #[inline]
     pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
         assert!(layout.size() != 0);
-        if let Some(a) = self.alloc_raw_without_grow(layout) {
-            return a;
+
+        // This loop executes once or twice: if allocation fails the first
+        // time, the `grow` ensures it will succeed the second time.
+        loop {
+            let start = self.start.get().addr();
+            let old_end = self.end.get();
+            let end = old_end.addr();
+
+            // Align allocated bytes so that `self.end` stays aligned to
+            // DROPLESS_ALIGNMENT.
+            let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT);
+
+            // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT.
+            unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) };
+
+            if let Some(sub) = end.checked_sub(bytes) {
+                let new_end = align_down(sub, layout.align());
+                if start <= new_end {
+                    let new_end = old_end.with_addr(new_end);
+                    // `new_end` is aligned to DROPLESS_ALIGNMENT as `align_down`
+                    // preserves alignment as both `end` and `bytes` are already
+                    // aligned to DROPLESS_ALIGNMENT.
+                    self.end.set(new_end);
+                    return new_end;
+                }
+            }
+
+            // No free space left. Allocate a new chunk to satisfy the request.
+            // On failure the grow will panic or abort.
+            self.grow(layout);
         }
-        // No free space left. Allocate a new chunk to satisfy the request.
-        // On failure the grow will panic or abort.
-        self.grow_and_alloc_raw(layout)
     }
 
     #[inline]
@@ -510,13 +494,7 @@ impl DroplessArena {
         assert!(!mem::needs_drop::<T>());
         assert!(mem::size_of::<T>() != 0);
 
-        let mem = if let Some(a) = self.alloc_raw_without_grow(Layout::for_value::<T>(&object)) {
-            a
-        } else {
-            // No free space left. Allocate a new chunk to satisfy the request.
-            // On failure the grow will panic or abort.
-            self.grow_and_alloc::<T>()
-        } as *mut T;
+        let mem = self.alloc_raw(Layout::new::<T>()) as *mut T;
 
         unsafe {
             // Write into uninitialized memory.
@@ -713,10 +691,10 @@ pub macro declare_arena([$($a:tt $name:ident: $ty:ty,)*]) {
         }
 
         #[allow(clippy::mut_from_ref)]
-        pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx, C>, C>(
-            &'a self,
+        pub fn alloc_from_iter<T: ArenaAllocatable<'tcx, C>, C>(
+            &self,
             iter: impl ::std::iter::IntoIterator<Item = T>,
-        ) -> &'a mut [T] {
+        ) -> &mut [T] {
             T::allocate_from_iter(self, iter)
         }
     }
diff --git a/compiler/rustc_ast/src/entry.rs b/compiler/rustc_ast/src/entry.rs
index 3370146193a..2dd5e96e513 100644
--- a/compiler/rustc_ast/src/entry.rs
+++ b/compiler/rustc_ast/src/entry.rs
@@ -1,3 +1,7 @@
+use crate::{attr, Attribute};
+use rustc_span::symbol::sym;
+use rustc_span::Symbol;
+
 #[derive(Debug)]
 pub enum EntryPointType {
     None,
@@ -6,3 +10,26 @@ pub enum EntryPointType {
     Start,
     OtherMain, // Not an entry point, but some other function named main
 }
+
+pub fn entry_point_type(
+    attrs: &[Attribute],
+    at_root: bool,
+    name: Option<Symbol>,
+) -> EntryPointType {
+    if attr::contains_name(attrs, sym::start) {
+        EntryPointType::Start
+    } else if attr::contains_name(attrs, sym::rustc_main) {
+        EntryPointType::RustcMainAttr
+    } else {
+        if let Some(name) = name && name == sym::main {
+            if at_root {
+                // This is a top-level function so it can be `main`.
+                EntryPointType::MainNamed
+            } else {
+                EntryPointType::OtherMain
+            }
+        } else {
+            EntryPointType::None
+        }
+    }
+}
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 53ff089d7b4..9c57f68f0b8 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -169,29 +169,15 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
     }
 }
 
-// Beware, this is duplicated in librustc_passes/entry.rs (with
-// `rustc_hir::Item`), so make sure to keep them in sync.
-fn entry_point_type(item: &ast::Item, depth: usize) -> EntryPointType {
+fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType {
     match item.kind {
         ast::ItemKind::Fn(..) => {
-            if attr::contains_name(&item.attrs, sym::start) {
-                EntryPointType::Start
-            } else if attr::contains_name(&item.attrs, sym::rustc_main) {
-                EntryPointType::RustcMainAttr
-            } else if item.ident.name == sym::main {
-                if depth == 0 {
-                    // This is a top-level function so can be 'main'
-                    EntryPointType::MainNamed
-                } else {
-                    EntryPointType::OtherMain
-                }
-            } else {
-                EntryPointType::None
-            }
+            rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(item.ident.name))
         }
         _ => EntryPointType::None,
     }
 }
+
 /// A folder used to remove any entry points (like fn main) because the harness
 /// generator will provide its own
 struct EntryPointCleaner<'a> {
@@ -210,7 +196,7 @@ impl<'a> MutVisitor for EntryPointCleaner<'a> {
         // Remove any #[rustc_main] or #[start] from the AST so it doesn't
         // clash with the one we're going to add, but mark it as
         // #[allow(dead_code)] to avoid printing warnings.
-        let item = match entry_point_type(&item, self.depth) {
+        let item = match entry_point_type(&item, self.depth == 0) {
             EntryPointType::MainNamed | EntryPointType::RustcMainAttr | EntryPointType::Start => {
                 item.map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| {
                     let allow_dead_code = attr::mk_attr_nested_word(
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index c64a4008996..6efbe149863 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -21,7 +21,7 @@ fn report_simd_type_validation_error(
 pub(super) fn codegen_simd_intrinsic_call<'tcx>(
     fx: &mut FunctionCx<'_, '_, 'tcx>,
     intrinsic: Symbol,
-    _args: GenericArgsRef<'tcx>,
+    generic_args: GenericArgsRef<'tcx>,
     args: &[mir::Operand<'tcx>],
     ret: CPlace<'tcx>,
     target: BasicBlock,
@@ -117,6 +117,54 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
             });
         }
 
+        // simd_shuffle_generic<T, U, const I: &[u32]>(x: T, y: T) -> U
+        sym::simd_shuffle_generic => {
+            let [x, y] = args else {
+                bug!("wrong number of args for intrinsic {intrinsic}");
+            };
+            let x = codegen_operand(fx, x);
+            let y = codegen_operand(fx, y);
+
+            if !x.layout().ty.is_simd() {
+                report_simd_type_validation_error(fx, intrinsic, span, x.layout().ty);
+                return;
+            }
+
+            let idx = generic_args[2]
+                .expect_const()
+                .eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(span))
+                .unwrap()
+                .unwrap_branch();
+
+            assert_eq!(x.layout(), y.layout());
+            let layout = x.layout();
+
+            let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
+            let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
+
+            assert_eq!(lane_ty, ret_lane_ty);
+            assert_eq!(idx.len() as u64, ret_lane_count);
+
+            let total_len = lane_count * 2;
+
+            let indexes =
+                idx.iter().map(|idx| idx.unwrap_leaf().try_to_u16().unwrap()).collect::<Vec<u16>>();
+
+            for &idx in &indexes {
+                assert!(u64::from(idx) < total_len, "idx {} out of range 0..{}", idx, total_len);
+            }
+
+            for (out_idx, in_idx) in indexes.into_iter().enumerate() {
+                let in_lane = if u64::from(in_idx) < lane_count {
+                    x.value_lane(fx, in_idx.into())
+                } else {
+                    y.value_lane(fx, u64::from(in_idx) - lane_count)
+                };
+                let out_lane = ret.place_lane(fx, u64::try_from(out_idx).unwrap());
+                out_lane.write_cvalue(fx, in_lane);
+            }
+        }
+
         // simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U
         sym::simd_shuffle => {
             let (x, y, idx) = match args {
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 9289c37d763..a97b803fc64 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -15,7 +15,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
-use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{self, GenericArgsRef, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_span::{sym, symbol::kw, Span, Symbol};
 use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
@@ -376,7 +376,9 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
             }
 
             _ if name.as_str().starts_with("simd_") => {
-                match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
+                match generic_simd_intrinsic(
+                    self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span,
+                ) {
                     Ok(llval) => llval,
                     Err(()) => return,
                 }
@@ -911,6 +913,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
     bx: &mut Builder<'_, 'll, 'tcx>,
     name: Symbol,
     callee_ty: Ty<'tcx>,
+    fn_args: GenericArgsRef<'tcx>,
     args: &[OperandRef<'tcx, &'ll Value>],
     ret_ty: Ty<'tcx>,
     llret_ty: &'ll Type,
@@ -1030,6 +1033,56 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         ));
     }
 
+    if name == sym::simd_shuffle_generic {
+        let idx = fn_args[2]
+            .expect_const()
+            .eval(tcx, ty::ParamEnv::reveal_all(), Some(span))
+            .unwrap()
+            .unwrap_branch();
+        let n = idx.len() as u64;
+
+        require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty });
+        let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
+        require!(
+            out_len == n,
+            InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len }
+        );
+        require!(
+            in_elem == out_ty,
+            InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
+        );
+
+        let total_len = in_len * 2;
+
+        let indices: Option<Vec<_>> = idx
+            .iter()
+            .enumerate()
+            .map(|(arg_idx, val)| {
+                let idx = val.unwrap_leaf().try_to_i32().unwrap();
+                if idx >= i32::try_from(total_len).unwrap() {
+                    bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds {
+                        span,
+                        name,
+                        arg_idx: arg_idx as u64,
+                        total_len: total_len.into(),
+                    });
+                    None
+                } else {
+                    Some(bx.const_i32(idx))
+                }
+            })
+            .collect();
+        let Some(indices) = indices else {
+            return Ok(bx.const_null(llret_ty));
+        };
+
+        return Ok(bx.shuffle_vector(
+            args[0].immediate(),
+            args[1].immediate(),
+            bx.const_vector(&indices),
+        ));
+    }
+
     if name == sym::simd_shuffle {
         // Make sure this is actually an array, since typeck only checks the length-suffixed
         // version of this intrinsic.
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 14b9894aad5..865e01d0aee 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -207,7 +207,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
         let def_id = instance.def_id();
 
-        if Some(def_id) == self.tcx.lang_items().panic_display()
+        if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
             let args = self.copy_fn_args(args)?;
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 129e74425b6..9d00ade477a 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -886,7 +886,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
                 // At this point, we are calling a function, `callee`, whose `DefId` is known...
 
-                // `begin_panic` and `panic_display` are generic functions that accept
+                // `begin_panic` and `#[rustc_const_panic_str]` functions accept generic
                 // types other than str. Check to enforce that only str can be used in
                 // const-eval.
 
@@ -898,8 +898,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                     }
                 }
 
-                // const-eval of the `panic_display` fn assumes the argument is `&&str`
-                if Some(callee) == tcx.lang_items().panic_display() {
+                // const-eval of `#[rustc_const_panic_str]` functions assumes the argument is `&&str`
+                if tcx.has_attr(callee, sym::rustc_const_panic_str) {
                     match args[0].ty(&self.ccx.body.local_decls, tcx).kind() {
                         ty::Ref(_, ty, _) if matches!(ty.kind(), ty::Ref(_, ty, _) if ty.is_str()) =>
                         {
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 18397af565f..65e697c8f3b 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -666,6 +666,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
     ),
+    // Ensure the argument to this function is &&str during const-check.
+    rustc_attr!(
+        rustc_const_panic_str, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
+    ),
 
     // ==========================================================================
     // Internal attributes, Layout related:
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 23b20543d53..4a89a6f7e39 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -230,7 +230,6 @@ language_item_table! {
     Panic,                   sym::panic,               panic_fn,                   Target::Fn,             GenericRequirement::Exact(0);
     PanicNounwind,           sym::panic_nounwind,      panic_nounwind,             Target::Fn,             GenericRequirement::Exact(0);
     PanicFmt,                sym::panic_fmt,           panic_fmt,                  Target::Fn,             GenericRequirement::None;
-    PanicDisplay,            sym::panic_display,       panic_display,              Target::Fn,             GenericRequirement::None;
     ConstPanicFmt,           sym::const_panic_fmt,     const_panic_fmt,            Target::Fn,             GenericRequirement::None;
     PanicBoundsCheck,        sym::panic_bounds_check,  panic_bounds_check_fn,      Target::Fn,             GenericRequirement::Exact(0);
     PanicMisalignedPointerDereference,        sym::panic_misaligned_pointer_dereference,  panic_misaligned_pointer_dereference_fn,      Target::Fn,             GenericRequirement::Exact(0);
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 3c0d977917f..c61719c1fd2 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -20,6 +20,7 @@ fn equate_intrinsic_type<'tcx>(
     it: &hir::ForeignItem<'_>,
     n_tps: usize,
     n_lts: usize,
+    n_cts: usize,
     sig: ty::PolyFnSig<'tcx>,
 ) {
     let (own_counts, span) = match &it.kind {
@@ -51,7 +52,7 @@ fn equate_intrinsic_type<'tcx>(
 
     if gen_count_ok(own_counts.lifetimes, n_lts, "lifetime")
         && gen_count_ok(own_counts.types, n_tps, "type")
-        && gen_count_ok(own_counts.consts, 0, "const")
+        && gen_count_ok(own_counts.consts, n_cts, "const")
     {
         let it_def_id = it.owner_id.def_id;
         check_function_signature(
@@ -489,7 +490,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     };
     let sig = tcx.mk_fn_sig(inputs, output, false, unsafety, Abi::RustIntrinsic);
     let sig = ty::Binder::bind_with_vars(sig, bound_vars);
-    equate_intrinsic_type(tcx, it, n_tps, n_lts, sig)
+    equate_intrinsic_type(tcx, it, n_tps, n_lts, 0, sig)
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -501,9 +502,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
 
     let name = it.ident.name;
 
-    let (n_tps, inputs, output) = match name {
+    let (n_tps, n_cts, inputs, output) = match name {
         sym::simd_eq | sym::simd_ne | sym::simd_lt | sym::simd_le | sym::simd_gt | sym::simd_ge => {
-            (2, vec![param(0), param(0)], param(1))
+            (2, 0, vec![param(0), param(0)], param(1))
         }
         sym::simd_add
         | sym::simd_sub
@@ -519,8 +520,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         | sym::simd_fmax
         | sym::simd_fpow
         | sym::simd_saturating_add
-        | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
-        sym::simd_arith_offset => (2, vec![param(0), param(1)], param(0)),
+        | sym::simd_saturating_sub => (1, 0, vec![param(0), param(0)], param(0)),
+        sym::simd_arith_offset => (2, 0, vec![param(0), param(1)], param(0)),
         sym::simd_neg
         | sym::simd_bswap
         | sym::simd_bitreverse
@@ -538,25 +539,25 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         | sym::simd_ceil
         | sym::simd_floor
         | sym::simd_round
-        | sym::simd_trunc => (1, vec![param(0)], param(0)),
-        sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)),
-        sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)),
-        sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)),
-        sym::simd_scatter => (3, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)),
-        sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
-        sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
+        | sym::simd_trunc => (1, 0, vec![param(0)], param(0)),
+        sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)),
+        sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)),
+        sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)),
+        sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)),
+        sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)),
+        sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)),
         sym::simd_cast
         | sym::simd_as
         | sym::simd_cast_ptr
         | sym::simd_expose_addr
-        | sym::simd_from_exposed_addr => (2, vec![param(0)], param(1)),
-        sym::simd_bitmask => (2, vec![param(0)], param(1)),
+        | sym::simd_from_exposed_addr => (2, 0, vec![param(0)], param(1)),
+        sym::simd_bitmask => (2, 0, vec![param(0)], param(1)),
         sym::simd_select | sym::simd_select_bitmask => {
-            (2, vec![param(0), param(1), param(1)], param(1))
+            (2, 0, vec![param(0), param(1), param(1)], param(1))
         }
-        sym::simd_reduce_all | sym::simd_reduce_any => (1, vec![param(0)], tcx.types.bool),
+        sym::simd_reduce_all | sym::simd_reduce_any => (1, 0, vec![param(0)], tcx.types.bool),
         sym::simd_reduce_add_ordered | sym::simd_reduce_mul_ordered => {
-            (2, vec![param(0), param(1)], param(1))
+            (2, 0, vec![param(0), param(1)], param(1))
         }
         sym::simd_reduce_add_unordered
         | sym::simd_reduce_mul_unordered
@@ -566,8 +567,9 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
         | sym::simd_reduce_min
         | 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)),
+        | sym::simd_reduce_max_nanless => (2, 0, vec![param(0)], param(1)),
+        sym::simd_shuffle => (3, 0, vec![param(0), param(0), param(1)], param(2)),
+        sym::simd_shuffle_generic => (2, 1, vec![param(0), param(0)], param(1)),
         _ => {
             let msg = format!("unrecognized platform-specific intrinsic function: `{name}`");
             tcx.sess.struct_span_err(it.span, msg).emit();
@@ -577,5 +579,5 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
 
     let sig = tcx.mk_fn_sig(inputs, output, false, hir::Unsafety::Unsafe, Abi::PlatformIntrinsic);
     let sig = ty::Binder::dummy(sig);
-    equate_intrinsic_type(tcx, it, n_tps, 0, sig)
+    equate_intrinsic_type(tcx, it, n_tps, 0, n_cts, sig)
 }
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 88c98fa979e..5fa65f33c76 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -329,41 +329,52 @@ fn bounds_from_generic_predicates<'tcx>(
             _ => {}
         }
     }
-    let generics = if types.is_empty() {
-        "".to_string()
-    } else {
-        format!(
-            "<{}>",
-            types
-                .keys()
-                .filter_map(|t| match t.kind() {
-                    ty::Param(_) => Some(t.to_string()),
-                    // Avoid suggesting the following:
-                    // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
-                    _ => None,
-                })
-                .collect::<Vec<_>>()
-                .join(", ")
-        )
-    };
+
     let mut where_clauses = vec![];
+    let mut types_str = vec![];
     for (ty, bounds) in types {
-        where_clauses
-            .extend(bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound))));
-    }
-    for projection in &projections {
-        let p = projection.skip_binder();
-        // FIXME: this is not currently supported syntax, we should be looking at the `types` and
-        // insert the associated types where they correspond, but for now let's be "lazy" and
-        // propose this instead of the following valid resugaring:
-        // `T: Trait, Trait::Assoc = K` → `T: Trait<Assoc = K>`
-        where_clauses.push(format!("{} = {}", tcx.def_path_str(p.projection_ty.def_id), p.term));
+        if let ty::Param(_) = ty.kind() {
+            let mut bounds_str = vec![];
+            for bound in bounds {
+                let mut projections_str = vec![];
+                for projection in &projections {
+                    let p = projection.skip_binder();
+                    let alias_ty = p.projection_ty;
+                    if bound == tcx.parent(alias_ty.def_id) && alias_ty.self_ty() == ty {
+                        let name = tcx.item_name(alias_ty.def_id);
+                        projections_str.push(format!("{} = {}", name, p.term));
+                    }
+                }
+                let bound_def_path = tcx.def_path_str(bound);
+                if projections_str.is_empty() {
+                    where_clauses.push(format!("{}: {}", ty, bound_def_path));
+                } else {
+                    bounds_str.push(format!("{}<{}>", bound_def_path, projections_str.join(", ")));
+                }
+            }
+            if bounds_str.is_empty() {
+                types_str.push(ty.to_string());
+            } else {
+                types_str.push(format!("{}: {}", ty, bounds_str.join(" + ")));
+            }
+        } else {
+            // Avoid suggesting the following:
+            // fn foo<T, <T as Trait>::Bar>(_: T) where T: Trait, <T as Trait>::Bar: Other {}
+            where_clauses.extend(
+                bounds.into_iter().map(|bound| format!("{}: {}", ty, tcx.def_path_str(bound))),
+            );
+        }
     }
+
+    let generics =
+        if types_str.is_empty() { "".to_string() } else { format!("<{}>", types_str.join(", ")) };
+
     let where_clauses = if where_clauses.is_empty() {
-        String::new()
+        "".to_string()
     } else {
         format!(" where {}", where_clauses.join(", "))
     };
+
     (generics, where_clauses)
 }
 
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index cd770c395e4..3ecd5b9cd34 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -63,11 +63,14 @@ impl<'tcx> BasicBlocks<'tcx> {
     }
 
     /// Returns basic blocks in a reverse postorder.
+    ///
+    /// See [`traversal::reverse_postorder`]'s docs to learn what is preorder traversal.
+    ///
+    /// [`traversal::reverse_postorder`]: crate::mir::traversal::reverse_postorder
     #[inline]
     pub fn reverse_postorder(&self) -> &[BasicBlock] {
         self.cache.reverse_postorder.get_or_init(|| {
-            let mut rpo: Vec<_> =
-                Postorder::new(&self.basic_blocks, START_BLOCK).map(|(bb, _)| bb).collect();
+            let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK).collect();
             rpo.reverse();
             rpo
         })
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index ec16a8470c4..a1ff8410eac 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -41,6 +41,12 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
     }
 }
 
+/// Preorder traversal of a graph.
+///
+/// This function creates an iterator over the `Body`'s basic blocks, that
+/// returns basic blocks in a preorder.
+///
+/// See [`Preorder`]'s docs to learn what is preorder traversal.
 pub fn preorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Preorder<'a, 'tcx> {
     Preorder::new(body, START_BLOCK)
 }
@@ -178,7 +184,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
         // When we yield `C` and call `traverse_successor`, we push `B` to the stack, but
         // since we've already visited `E`, that child isn't added to the stack. The last
         // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A]
-        while let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() && let Some(bb) = iter.next_back() {
+        while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) {
             if self.visited.insert(bb) {
                 if let Some(term) = &self.basic_blocks[bb].terminator {
                     self.visit_stack.push((bb, term.successors()));
@@ -188,16 +194,14 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
-    type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
+impl<'tcx> Iterator for Postorder<'_, 'tcx> {
+    type Item = BasicBlock;
 
-    fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> {
-        let next = self.visit_stack.pop();
-        if next.is_some() {
-            self.traverse_successor();
-        }
+    fn next(&mut self) -> Option<BasicBlock> {
+        let (bb, _) = self.visit_stack.pop()?;
+        self.traverse_successor();
 
-        next.map(|(bb, _)| (bb, &self.basic_blocks[bb]))
+        Some(bb)
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
@@ -215,10 +219,14 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
     }
 }
 
-/// Creates an iterator over the `Body`'s basic blocks, that:
+/// Postorder traversal of a graph.
+///
+/// This function creates an iterator over the `Body`'s basic blocks, that:
 /// - returns basic blocks in a postorder,
 /// - traverses the `BasicBlocks` CFG cache's reverse postorder backwards, and does not cache the
 ///   postorder itself.
+///
+/// See [`Postorder`]'s docs to learn what is postorder traversal.
 pub fn postorder<'a, 'tcx>(
     body: &'a Body<'tcx>,
 ) -> impl Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> + ExactSizeIterator + DoubleEndedIterator
@@ -226,7 +234,28 @@ pub fn postorder<'a, 'tcx>(
     reverse_postorder(body).rev()
 }
 
-/// Reverse postorder traversal of a graph
+/// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular
+/// order.
+///
+/// This is clearer than writing `preorder` in cases where the order doesn't matter.
+pub fn reachable<'a, 'tcx>(
+    body: &'a Body<'tcx>,
+) -> impl 'a + Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> {
+    preorder(body)
+}
+
+/// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`.
+pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet<BasicBlock> {
+    let mut iter = preorder(body);
+    iter.by_ref().for_each(drop);
+    iter.visited
+}
+
+/// Reverse postorder traversal of a graph.
+///
+/// This function creates an iterator over the `Body`'s basic blocks, that:
+/// - returns basic blocks in a reverse postorder,
+/// - makes use of the `BasicBlocks` CFG cache's reverse postorder.
 ///
 /// Reverse postorder is the reverse order of a postorder traversal.
 /// This is different to a preorder traversal and represents a natural
@@ -246,65 +275,6 @@ pub fn postorder<'a, 'tcx>(
 /// A reverse postorder traversal of this graph is either `A B C D` or `A C B D`
 /// Note that for a graph containing no loops (i.e., A DAG), this is equivalent to
 /// a topological sort.
-///
-/// Construction of a `ReversePostorder` traversal requires doing a full
-/// postorder traversal of the graph, therefore this traversal should be
-/// constructed as few times as possible. Use the `reset` method to be able
-/// to re-use the traversal
-#[derive(Clone)]
-pub struct ReversePostorder<'a, 'tcx> {
-    body: &'a Body<'tcx>,
-    blocks: Vec<BasicBlock>,
-    idx: usize,
-}
-
-impl<'a, 'tcx> ReversePostorder<'a, 'tcx> {
-    pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> {
-        let blocks: Vec<_> = Postorder::new(&body.basic_blocks, root).map(|(bb, _)| bb).collect();
-        let len = blocks.len();
-        ReversePostorder { body, blocks, idx: len }
-    }
-}
-
-impl<'a, 'tcx> Iterator for ReversePostorder<'a, 'tcx> {
-    type Item = (BasicBlock, &'a BasicBlockData<'tcx>);
-
-    fn next(&mut self) -> Option<(BasicBlock, &'a BasicBlockData<'tcx>)> {
-        if self.idx == 0 {
-            return None;
-        }
-        self.idx -= 1;
-
-        self.blocks.get(self.idx).map(|&bb| (bb, &self.body[bb]))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (self.idx, Some(self.idx))
-    }
-}
-
-impl<'a, 'tcx> ExactSizeIterator for ReversePostorder<'a, 'tcx> {}
-
-/// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular
-/// order.
-///
-/// This is clearer than writing `preorder` in cases where the order doesn't matter.
-pub fn reachable<'a, 'tcx>(
-    body: &'a Body<'tcx>,
-) -> impl 'a + Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> {
-    preorder(body)
-}
-
-/// Returns a `BitSet` containing all basic blocks reachable from the `START_BLOCK`.
-pub fn reachable_as_bitset(body: &Body<'_>) -> BitSet<BasicBlock> {
-    let mut iter = preorder(body);
-    (&mut iter).for_each(drop);
-    iter.visited
-}
-
-/// Creates an iterator over the `Body`'s basic blocks, that:
-/// - returns basic blocks in a reverse postorder,
-/// - makes use of the `BasicBlocks` CFG cache's reverse postorder.
 pub fn reverse_postorder<'a, 'tcx>(
     body: &'a Body<'tcx>,
 ) -> impl Iterator<Item = (BasicBlock, &'a BasicBlockData<'tcx>)> + ExactSizeIterator + DoubleEndedIterator
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 4f71704b885..c92d0b878ea 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -52,31 +52,6 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
     configure_main(tcx, &ctxt)
 }
 
-// Beware, this is duplicated in `librustc_builtin_macros/test_harness.rs`
-// (with `ast::Item`), so make sure to keep them in sync.
-// A small optimization was added so that hir::Item is fetched only when needed.
-// An equivalent optimization was not applied to the duplicated code in test_harness.rs.
-fn entry_point_type(ctxt: &EntryContext<'_>, id: ItemId, at_root: bool) -> EntryPointType {
-    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
-    if attr::contains_name(attrs, sym::start) {
-        EntryPointType::Start
-    } else if attr::contains_name(attrs, sym::rustc_main) {
-        EntryPointType::RustcMainAttr
-    } else {
-        if let Some(name) = ctxt.tcx.opt_item_name(id.owner_id.to_def_id())
-            && name == sym::main {
-            if at_root {
-                // This is a top-level function so can be `main`.
-                EntryPointType::MainNamed
-            } else {
-                EntryPointType::OtherMain
-            }
-        } else {
-            EntryPointType::None
-        }
-    }
-}
-
 fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
     let attrs = ctxt.tcx.hir().attrs(id.hir_id());
     attr::find_by_name(attrs, sym).map(|attr| attr.span)
@@ -85,7 +60,13 @@ fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Opti
 fn find_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
     let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
 
-    match entry_point_type(ctxt, id, at_root) {
+    let attrs = ctxt.tcx.hir().attrs(id.hir_id());
+    let entry_point_type = rustc_ast::entry::entry_point_type(
+        attrs,
+        at_root,
+        ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
+    );
+    match entry_point_type {
         EntryPointType::None => {
             if let Some(span) = attr_span_by_symbol(ctxt, id, sym::unix_sigpipe) {
                 ctxt.tcx.sess.emit_err(AttrOnlyOnMain { span, attr: sym::unix_sigpipe });
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 907a6b1c46c..110286255c5 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1169,6 +1169,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                     return;
                 }
 
+                if ident.name == kw::Underscore {
+                    return;
+                }
+
                 let child_accessible =
                     accessible && this.is_accessible_from(name_binding.vis, parent_scope.module);
 
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 441aafd1257..1a9dea99f64 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -86,6 +86,10 @@ impl<'tcx> Tables<'tcx> {
         stable_mir::ty::ImplDef(self.create_def_id(did))
     }
 
+    pub fn region_def(&mut self, did: DefId) -> stable_mir::ty::RegionDef {
+        stable_mir::ty::RegionDef(self.create_def_id(did))
+    }
+
     pub fn prov(&mut self, aid: AllocId) -> stable_mir::ty::Prov {
         stable_mir::ty::Prov(self.create_alloc_id(aid))
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 5ff17613b4e..c6c97ce35e8 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,7 +7,8 @@
 //!
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
-use hir::def::DefKind;
+use crate::rustc_smir::hir::def::DefKind;
+use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region};
 use rustc_hir as hir;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{alloc_range, AllocId};
@@ -1500,9 +1501,39 @@ impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
 impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
     type T = stable_mir::ty::Region;
 
-    fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
-        // FIXME: add a real implementation of stable regions
-        opaque(self)
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        Region { kind: self.kind().stable(tables) }
+    }
+}
+
+impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
+    type T = stable_mir::ty::RegionKind;
+
+    fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+        use stable_mir::ty::RegionKind;
+        match self {
+            ty::ReEarlyBound(early_reg) => RegionKind::ReEarlyBound(EarlyBoundRegion {
+                def_id: tables.region_def(early_reg.def_id),
+                index: early_reg.index,
+                name: early_reg.name.to_string(),
+            }),
+            ty::ReLateBound(db_index, bound_reg) => RegionKind::ReLateBound(
+                db_index.as_u32(),
+                BoundRegion { var: bound_reg.var.as_u32(), kind: bound_reg.kind.stable(tables) },
+            ),
+            ty::ReStatic => RegionKind::ReStatic,
+            ty::RePlaceholder(place_holder) => {
+                RegionKind::RePlaceholder(stable_mir::ty::Placeholder {
+                    universe: place_holder.universe.as_u32(),
+                    bound: BoundRegion {
+                        var: place_holder.bound.var.as_u32(),
+                        kind: place_holder.bound.kind.stable(tables),
+                    },
+                })
+            }
+            ty::ReErased => RegionKind::ReErased,
+            _ => unreachable!("{self:?}"),
+        }
     }
 }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 382754be2ca..e4fafbc12d3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1104,7 +1104,6 @@ symbols! {
         panic_abort,
         panic_bounds_check,
         panic_cannot_unwind,
-        panic_display,
         panic_fmt,
         panic_handler,
         panic_impl,
@@ -1299,6 +1298,7 @@ symbols! {
         rustc_coherence_is_core,
         rustc_coinductive,
         rustc_confusables,
+        rustc_const_panic_str,
         rustc_const_stable,
         rustc_const_unstable,
         rustc_conversion_suggestion,
@@ -1465,6 +1465,7 @@ symbols! {
         simd_shl,
         simd_shr,
         simd_shuffle,
+        simd_shuffle_generic,
         simd_sub,
         simd_trunc,
         simd_xor,
diff --git a/compiler/stable_mir/src/fold.rs b/compiler/stable_mir/src/fold.rs
index 1da123e922b..6471b2c2a3a 100644
--- a/compiler/stable_mir/src/fold.rs
+++ b/compiler/stable_mir/src/fold.rs
@@ -4,17 +4,20 @@ use crate::Opaque;
 
 use super::ty::{
     Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind,
-    GenericArgs, Promoted, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst,
+    GenericArgs, Promoted, Region, RigidTy, TermKind, Ty, TyKind, UnevaluatedConst,
 };
 
 pub trait Folder: Sized {
     type Break;
-    fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
+    fn fold_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
         ty.super_fold(self)
     }
     fn fold_const(&mut self, c: &Const) -> ControlFlow<Self::Break, Const> {
         c.super_fold(self)
     }
+    fn fold_reg(&mut self, reg: &Region) -> ControlFlow<Self::Break, Region> {
+        reg.super_fold(self)
+    }
 }
 
 pub trait Foldable: Sized + Clone {
@@ -26,7 +29,7 @@ pub trait Foldable: Sized + Clone {
 
 impl Foldable for Ty {
     fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
-        folder.visit_ty(self)
+        folder.fold_ty(self)
     }
     fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
         let mut kind = self.kind();
@@ -106,6 +109,15 @@ impl Foldable for GenericArgs {
     }
 }
 
+impl Foldable for Region {
+    fn fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
+        folder.fold_reg(self)
+    }
+    fn super_fold<V: Folder>(&self, _: &mut V) -> ControlFlow<V::Break, Self> {
+        ControlFlow::Continue(self.clone())
+    }
+}
+
 impl Foldable for GenericArgKind {
     fn super_fold<V: Folder>(&self, folder: &mut V) -> ControlFlow<V::Break, Self> {
         let mut this = self.clone();
@@ -136,7 +148,10 @@ impl Foldable for RigidTy {
             }
             RigidTy::Slice(inner) => *inner = inner.fold(folder)?,
             RigidTy::RawPtr(ty, _) => *ty = ty.fold(folder)?,
-            RigidTy::Ref(_, ty, _) => *ty = ty.fold(folder)?,
+            RigidTy::Ref(reg, ty, _) => {
+                *reg = reg.fold(folder)?;
+                *ty = ty.fold(folder)?
+            }
             RigidTy::FnDef(_, args) => *args = args.fold(folder)?,
             RigidTy::FnPtr(sig) => *sig = sig.fold(folder)?,
             RigidTy::Closure(_, args) => *args = args.fold(folder)?,
@@ -214,7 +229,7 @@ pub enum Never {}
 impl Folder for GenericArgs {
     type Break = Never;
 
-    fn visit_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
+    fn fold_ty(&mut self, ty: &Ty) -> ControlFlow<Self::Break, Ty> {
         ControlFlow::Continue(match ty.kind() {
             TyKind::Param(p) => self[p],
             _ => *ty,
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 82007e30683..6029e3c11ad 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -1,7 +1,7 @@
 use super::{
     mir::Safety,
     mir::{Body, Mutability},
-    with, AllocId, DefId,
+    with, AllocId, DefId, Symbol,
 };
 use crate::Opaque;
 use std::fmt::{self, Debug, Formatter};
@@ -34,7 +34,46 @@ pub struct Const {
 }
 
 type Ident = Opaque;
-pub type Region = Opaque;
+
+#[derive(Debug, Clone)]
+pub struct Region {
+    pub kind: RegionKind,
+}
+
+#[derive(Debug, Clone)]
+pub enum RegionKind {
+    ReEarlyBound(EarlyBoundRegion),
+    ReLateBound(DebruijnIndex, BoundRegion),
+    ReStatic,
+    RePlaceholder(Placeholder<BoundRegion>),
+    ReErased,
+}
+
+pub(crate) type DebruijnIndex = u32;
+
+#[derive(Debug, Clone)]
+pub struct EarlyBoundRegion {
+    pub def_id: RegionDef,
+    pub index: u32,
+    pub name: Symbol,
+}
+
+pub(crate) type BoundVar = u32;
+
+#[derive(Debug, Clone)]
+pub struct BoundRegion {
+    pub var: BoundVar,
+    pub kind: BoundRegionKind,
+}
+
+pub(crate) type UniverseIndex = u32;
+
+#[derive(Debug, Clone)]
+pub struct Placeholder<T> {
+    pub universe: UniverseIndex,
+    pub bound: T,
+}
+
 #[derive(Clone, Copy, PartialEq, Eq)]
 pub struct Span(pub usize);
 
@@ -152,6 +191,9 @@ pub struct ConstDef(pub DefId);
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct ImplDef(pub DefId);
 
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct RegionDef(pub DefId);
+
 #[derive(Clone, Debug)]
 pub struct GenericArgs(pub Vec<GenericArgKind>);
 
diff --git a/compiler/stable_mir/src/visitor.rs b/compiler/stable_mir/src/visitor.rs
index 9c3b4cd994a..96100958138 100644
--- a/compiler/stable_mir/src/visitor.rs
+++ b/compiler/stable_mir/src/visitor.rs
@@ -4,7 +4,7 @@ use crate::Opaque;
 
 use super::ty::{
     Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs,
-    Promoted, RigidTy, TermKind, Ty, UnevaluatedConst,
+    Promoted, Region, RigidTy, TermKind, Ty, UnevaluatedConst,
 };
 
 pub trait Visitor: Sized {
@@ -15,6 +15,9 @@ pub trait Visitor: Sized {
     fn visit_const(&mut self, c: &Const) -> ControlFlow<Self::Break> {
         c.super_visit(self)
     }
+    fn visit_reg(&mut self, reg: &Region) -> ControlFlow<Self::Break> {
+        reg.super_visit(self)
+    }
 }
 
 pub trait Visitable {
@@ -101,6 +104,16 @@ impl Visitable for GenericArgs {
     }
 }
 
+impl Visitable for Region {
+    fn visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
+        visitor.visit_reg(self)
+    }
+
+    fn super_visit<V: Visitor>(&self, _: &mut V) -> ControlFlow<V::Break> {
+        ControlFlow::Continue(())
+    }
+}
+
 impl Visitable for GenericArgKind {
     fn super_visit<V: Visitor>(&self, visitor: &mut V) -> ControlFlow<V::Break> {
         match self {
@@ -128,7 +141,10 @@ impl Visitable for RigidTy {
             }
             RigidTy::Slice(inner) => inner.visit(visitor),
             RigidTy::RawPtr(ty, _) => ty.visit(visitor),
-            RigidTy::Ref(_, ty, _) => ty.visit(visitor),
+            RigidTy::Ref(reg, ty, _) => {
+                reg.visit(visitor);
+                ty.visit(visitor)
+            }
             RigidTy::FnDef(_, args) => args.visit(visitor),
             RigidTy::FnPtr(sig) => sig.visit(visitor),
             RigidTy::Closure(_, args) => args.visit(visitor),
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 9df971af49c..61f4bfc54b0 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1618,7 +1618,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     #[must_use]
     #[stable(feature = "arc_counts", since = "1.15.0")]
     pub fn weak_count(this: &Self) -> usize {
-        let cnt = this.inner().weak.load(Acquire);
+        let cnt = this.inner().weak.load(Relaxed);
         // If the weak count is currently locked, the value of the
         // count was 0 just before taking the lock.
         if cnt == usize::MAX { 0 } else { cnt - 1 }
@@ -1648,7 +1648,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     #[must_use]
     #[stable(feature = "arc_counts", since = "1.15.0")]
     pub fn strong_count(this: &Self) -> usize {
-        this.inner().strong.load(Acquire)
+        this.inner().strong.load(Relaxed)
     }
 
     /// Increments the strong reference count on the `Arc<T>` associated with the
@@ -2803,7 +2803,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     #[must_use]
     #[stable(feature = "weak_counts", since = "1.41.0")]
     pub fn strong_count(&self) -> usize {
-        if let Some(inner) = self.inner() { inner.strong.load(Acquire) } else { 0 }
+        if let Some(inner) = self.inner() { inner.strong.load(Relaxed) } else { 0 }
     }
 
     /// Gets an approximation of the number of `Weak` pointers pointing to this
@@ -2822,7 +2822,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
     pub fn weak_count(&self) -> usize {
         if let Some(inner) = self.inner() {
             let weak = inner.weak.load(Acquire);
-            let strong = inner.strong.load(Acquire);
+            let strong = inner.strong.load(Relaxed);
             if strong == 0 {
                 0
             } else {
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index d7abc9a0e23..5244e478018 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -930,7 +930,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
 /// This function is not magic; it is literally defined as
 ///
 /// ```
-/// pub fn drop<T>(_x: T) { }
+/// pub fn drop<T>(_x: T) {}
 /// ```
 ///
 /// Because `_x` is moved into the function, it is automatically dropped before
diff --git a/library/core/src/panic.rs b/library/core/src/panic.rs
index 386f5fcbd6a..a00fd322b3c 100644
--- a/library/core/src/panic.rs
+++ b/library/core/src/panic.rs
@@ -47,6 +47,7 @@ pub macro panic_2015 {
 #[allow_internal_unstable(core_panic, const_format_args)]
 #[rustc_diagnostic_item = "core_panic_2021_macro"]
 #[rustc_macro_transparency = "semitransparent"]
+#[cfg(any(bootstrap, feature = "panic_immediate_abort"))]
 pub macro panic_2021 {
     () => (
         $crate::panicking::panic("explicit panic")
@@ -63,6 +64,50 @@ pub macro panic_2021 {
 }
 
 #[doc(hidden)]
+#[unstable(feature = "edition_panic", issue = "none", reason = "use panic!() instead")]
+#[allow_internal_unstable(
+    core_panic,
+    core_intrinsics,
+    const_dispatch,
+    const_eval_select,
+    const_format_args,
+    rustc_attrs
+)]
+#[rustc_diagnostic_item = "core_panic_2021_macro"]
+#[rustc_macro_transparency = "semitransparent"]
+#[cfg(not(any(bootstrap, feature = "panic_immediate_abort")))]
+pub macro panic_2021 {
+    () => ({
+        // Create a function so that the argument for `track_caller`
+        // can be moved inside if possible.
+        #[cold]
+        #[track_caller]
+        #[inline(never)]
+        const fn panic_cold_explicit() -> ! {
+            $crate::panicking::panic_explicit()
+        }
+        panic_cold_explicit();
+    }),
+    // Special-case the single-argument case for const_panic.
+    ("{}", $arg:expr $(,)?) => ({
+        #[cold]
+        #[track_caller]
+        #[inline(never)]
+        #[rustc_const_panic_str] // enforce a &&str argument in const-check and hook this by const-eval
+        #[rustc_do_not_const_check] // hooked by const-eval
+        const fn panic_cold_display<T: $crate::fmt::Display>(arg: &T) -> ! {
+            $crate::panicking::panic_display(arg)
+        }
+        panic_cold_display(&$arg);
+    }),
+    ($($t:tt)+) => ({
+        // Semicolon to prevent temporaries inside the formatting machinery from
+        // being considered alive in the caller after the panic_fmt call.
+        $crate::panicking::panic_fmt($crate::const_format_args!($($t)+));
+    }),
+}
+
+#[doc(hidden)]
 #[unstable(feature = "edition_panic", issue = "none", reason = "use unreachable!() instead")]
 #[allow_internal_unstable(core_panic)]
 #[rustc_diagnostic_item = "unreachable_2015_macro"]
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index e6cdffd96af..1a32cf92ffb 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -152,6 +152,14 @@ pub const fn panic_str(expr: &str) -> ! {
     panic_display(&expr);
 }
 
+#[track_caller]
+#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
+#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[rustc_const_unstable(feature = "core_panic", issue = "none")]
+pub const fn panic_explicit() -> ! {
+    panic_display(&"explicit panic");
+}
+
 #[inline]
 #[track_caller]
 #[rustc_diagnostic_item = "unreachable_display"] // needed for `non-fmt-panics` lint
@@ -161,8 +169,10 @@ pub fn unreachable_display<T: fmt::Display>(x: &T) -> ! {
 
 #[inline]
 #[track_caller]
-#[lang = "panic_display"] // needed for const-evaluated panics
 #[rustc_do_not_const_check] // hooked by const-eval
+#[cfg_attr(bootstrap, lang = "panic_display")]
+// enforce a &&str argument in const-check and hook this by const-eval
+#[cfg_attr(not(bootstrap), rustc_const_panic_str)]
 #[rustc_const_unstable(feature = "core_panic", issue = "none")]
 pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
     panic_fmt(format_args!("{}", *x));
diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs
index 3f3e19c55d4..ff538d55c60 100644
--- a/library/core/src/sync/exclusive.rs
+++ b/library/core/src/sync/exclusive.rs
@@ -2,6 +2,8 @@
 
 use core::fmt;
 use core::future::Future;
+use core::marker::Tuple;
+use core::ops::{Generator, GeneratorState};
 use core::pin::Pin;
 use core::task::{Context, Poll};
 
@@ -168,10 +170,52 @@ impl<T> From<T> for Exclusive<T> {
 }
 
 #[unstable(feature = "exclusive_wrapper", issue = "98407")]
-impl<T: Future + ?Sized> Future for Exclusive<T> {
+impl<F, Args> FnOnce<Args> for Exclusive<F>
+where
+    F: FnOnce<Args>,
+    Args: Tuple,
+{
+    type Output = F::Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
+        self.into_inner().call_once(args)
+    }
+}
+
+#[unstable(feature = "exclusive_wrapper", issue = "98407")]
+impl<F, Args> FnMut<Args> for Exclusive<F>
+where
+    F: FnMut<Args>,
+    Args: Tuple,
+{
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
+        self.get_mut().call_mut(args)
+    }
+}
+
+#[unstable(feature = "exclusive_wrapper", issue = "98407")]
+impl<T> Future for Exclusive<T>
+where
+    T: Future + ?Sized,
+{
     type Output = T::Output;
+
     #[inline]
     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
         self.get_pin_mut().poll(cx)
     }
 }
+
+#[unstable(feature = "generator_trait", issue = "43122")] // also #98407
+impl<R, G> Generator<R> for Exclusive<G>
+where
+    G: Generator<R> + ?Sized,
+{
+    type Yield = G::Yield;
+    type Return = G::Return;
+
+    #[inline]
+    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
+        G::resume(self.get_pin_mut(), arg)
+    }
+}
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index c638cc61856..005d8c76704 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -58,6 +58,8 @@ pub use core::time::TryFromFloatSecsError;
 /// some seconds may be longer than others). An instant may jump forwards or
 /// experience time dilation (slow down or speed up), but it will never go
 /// backwards.
+/// As part of this non-guarantee it is also not specified whether system suspends count as
+/// elapsed time or not. The behavior varies across platforms and rust versions.
 ///
 /// Instants are opaque types that can only be compared to one another. There is
 /// no method to get "the number of seconds" from an instant. Instead, it only
diff --git a/rust-bors.toml b/rust-bors.toml
new file mode 100644
index 00000000000..54f4f641248
--- /dev/null
+++ b/rust-bors.toml
@@ -0,0 +1 @@
+timeout = 7200
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index fac0cdf2038..4af97b2f466 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -1042,6 +1042,12 @@ def bootstrap(args):
     """Configure, fetch, build and run the initial bootstrap"""
     rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
 
+    if not os.path.exists(os.path.join(rust_root, '.git')) and \
+            os.path.exists(os.path.join(rust_root, '.github')):
+        eprint("warn: Looks like you are trying to bootstrap Rust from a source that is neither a "
+               "git clone nor distributed tarball.\nThis build may fail due to missing submodules "
+               "unless you put them in place manually.")
+
     # Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`,
     # then `config.toml` in the root directory.
     toml_path = args.config or os.getenv('RUST_BOOTSTRAP_CONFIG')
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index b62aa999246..85cd8abb995 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -45,6 +45,23 @@ fn sanitize_sh(path: &Path) -> String {
     }
 }
 
+fn is_dir_writable_for_user(dir: &PathBuf) -> bool {
+    let tmp_file = dir.join(".tmp");
+    match fs::File::create(&tmp_file) {
+        Ok(_) => {
+            fs::remove_file(tmp_file).unwrap();
+            true
+        }
+        Err(e) => {
+            if e.kind() == std::io::ErrorKind::PermissionDenied {
+                false
+            } else {
+                panic!("Failed the write access check for the current user. {}", e);
+            }
+        }
+    }
+}
+
 fn install_sh(
     builder: &Builder<'_>,
     package: &str,
@@ -56,6 +73,17 @@ fn install_sh(
 
     let prefix = default_path(&builder.config.prefix, "/usr/local");
     let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
+
+    // Sanity check for the user write access on prefix and sysconfdir
+    assert!(
+        is_dir_writable_for_user(&prefix),
+        "User doesn't have write access on `install.prefix` path in the `config.toml`.",
+    );
+    assert!(
+        is_dir_writable_for_user(&sysconfdir),
+        "User doesn't have write access on `install.sysconfdir` path in `config.toml`."
+    );
+
     let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
     let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust"));
     let mandir = prefix.join(default_path(&builder.config.mandir, "share/man"));
@@ -92,6 +120,9 @@ fn prepare_dir(mut path: PathBuf) -> String {
     // More information on the environment variable is available here:
     // https://www.gnu.org/prep/standards/html_node/DESTDIR.html
     if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
+        // Sanity check for the user write access on DESTDIR
+        assert!(is_dir_writable_for_user(&destdir), "User doesn't have write access on DESTDIR.");
+
         let without_destdir = path.clone();
         path = destdir;
         // Custom .join() which ignores disk roots.
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index a9865e262fe..0b67079917c 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -6,6 +6,13 @@ Q := @
 BOOTSTRAP_ARGS :=
 endif
 
+# Pass `-jN` to the bootstrap if it is specified.
+ifdef MAKEFLAGS
+  ifneq (,$(findstring -j, $(MAKEFLAGS)))
+    BOOTSTRAP_ARGS += $(filter -j%, $(MAKEFLAGS))
+  endif
+endif
+
 BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
 
 all:
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index b83b198780b..2e645683713 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -271,7 +271,7 @@ For targets: `loongarch64-unknown-linux-gnu`
 - Operating System > Linux kernel version = 5.19.16
 - Binary utilities > Version of binutils = 2.40
 - C-library > glibc version = 2.36
-- C compiler > gcc version = 13.1.0
+- C compiler > gcc version = 13.2.0
 - C compiler > C++ = ENABLE -- to cross compile LLVM
 
 ### `mips-linux-gnu.defconfig`
@@ -407,7 +407,7 @@ For targets: `riscv64-unknown-linux-gnu`
 - Target options > Bitness = 64-bit
 - Operating System > Target OS = linux
 - Operating System > Linux kernel version = 4.20.17
-- Binary utilities > Version of binutils = 2.32
+- Binary utilities > Version of binutils = 2.36.1
 - C-library > glibc version = 2.29
 - C compiler > gcc version = 8.5.0
 - C compiler > C++ = ENABLE -- to cross compile LLVM
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
index 78689c429c2..55c737bd0aa 100644
--- a/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-linux/Dockerfile
@@ -3,9 +3,8 @@ FROM ubuntu:22.04
 COPY scripts/cross-apt-packages.sh /scripts/
 RUN sh /scripts/cross-apt-packages.sh
 
-# The latest released version does not support LoongArch.
-COPY scripts/crosstool-ng-git.sh /scripts/
-RUN sh /scripts/crosstool-ng-git.sh
+COPY scripts/crosstool-ng.sh /scripts/
+RUN sh /scripts/crosstool-ng.sh
 
 COPY scripts/rustbuild-setup.sh /scripts/
 RUN sh /scripts/rustbuild-setup.sh
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 670e37b9d01..01b46118b9c 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -128,6 +128,8 @@ ENV TARGETS=$TARGETS,armv7-unknown-linux-gnueabi
 ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabi
 ENV TARGETS=$TARGETS,i686-unknown-freebsd
 ENV TARGETS=$TARGETS,x86_64-unknown-none
+ENV TARGETS=$TARGETS,loongarch64-unknown-none
+ENV TARGETS=$TARGETS,loongarch64-unknown-none-softfloat
 ENV TARGETS=$TARGETS,aarch64-unknown-uefi
 ENV TARGETS=$TARGETS,i686-unknown-uefi
 ENV TARGETS=$TARGETS,x86_64-unknown-uefi
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 6f1b2a6a638..c04121a8bee 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -84,7 +84,8 @@ ENV RUST_CONFIGURE_ARGS \
       --set llvm.ninja=false \
       --set rust.jemalloc \
       --set rust.use-lld=true \
-      --set rust.lto=thin
+      --set rust.lto=thin \
+      --set rust.codegen-units=1
 
 ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
     ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh
deleted file mode 100644
index b8d39915327..00000000000
--- a/src/ci/docker/scripts/crosstool-ng-git.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-set -ex
-
-URL=https://github.com/crosstool-ng/crosstool-ng
-REV=227d99d7f3115f3a078595a580d2b307dcd23e93
-
-mkdir crosstool-ng
-cd crosstool-ng
-git init
-git fetch --depth=1 ${URL} ${REV}
-git reset --hard FETCH_HEAD
-./bootstrap
-./configure --prefix=/usr/local
-make -j$(nproc)
-make install
-cd ..
-rm -rf crosstool-ng
diff --git a/src/ci/docker/scripts/crosstool-ng.sh b/src/ci/docker/scripts/crosstool-ng.sh
index a28d7bde2ac..c3ee19b8d2c 100644
--- a/src/ci/docker/scripts/crosstool-ng.sh
+++ b/src/ci/docker/scripts/crosstool-ng.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 set -ex
 
-CT_NG=1.25.0
+CT_NG=1.26.0
 
 url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-$CT_NG.tar.gz"
 curl -Lf $url | tar xzf -
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index cbf848cb4a3..6d25b2c9cc2 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -691,7 +691,7 @@ jobs:
     env:
       DIST_TRY_BUILD: 1
       <<: [*shared-ci-variables, *prod-variables]
-    if: github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'
+    if: github.event_name == 'push' && (((github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust') || ((github.ref == 'refs/heads/automation/bors/try') && github.repository == 'rust-lang/rust'))
     strategy:
       matrix:
         include:
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 5701b002f21..ff831a20504 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -157,6 +157,8 @@ target | std | notes
 `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD
 `i686-unknown-linux-musl` | ✓ | 32-bit Linux with MUSL
 [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
+[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64D ABI)
+[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64S ABI)
 `mips-unknown-linux-musl` | ✓ | MIPS Linux with MUSL
 `mips64-unknown-linux-muslabi64` | ✓ | MIPS64 Linux, n64 ABI, MUSL
 `mips64el-unknown-linux-muslabi64` | ✓ | MIPS64 (LE) Linux, n64 ABI, MUSL
@@ -274,8 +276,6 @@ target | std | host | notes
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
-[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64D ABI)
-[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64S ABI)
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
 [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL
diff --git a/src/doc/rustc/src/platform-support/loongarch-none.md b/src/doc/rustc/src/platform-support/loongarch-none.md
index d0ae3425fa8..68d7c9d85e4 100644
--- a/src/doc/rustc/src/platform-support/loongarch-none.md
+++ b/src/doc/rustc/src/platform-support/loongarch-none.md
@@ -1,6 +1,6 @@
 # `loongarch*-unknown-none*`
 
-**Tier: 3**
+**Tier: 2**
 
 Freestanding/bare-metal LoongArch64 binaries in ELF format: firmware, kernels, etc.
 
diff --git a/src/doc/unstable-book/src/language-features/plugin.md b/src/doc/unstable-book/src/language-features/plugin.md
index 189cc910a8d..d9421a428f1 100644
--- a/src/doc/unstable-book/src/language-features/plugin.md
+++ b/src/doc/unstable-book/src/language-features/plugin.md
@@ -33,7 +33,7 @@ of a library.
 Plugins can extend [Rust's lint
 infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with
 additional checks for code style, safety, etc. Now let's write a plugin
-[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/auxiliary/lint-plugin-test.rs)
+[`lint-plugin-test.rs`](https://github.com/rust-lang/rust/blob/master/tests/ui-fulldeps/plugin/auxiliary/lint-plugin-test.rs)
 that warns about any item named `lintme`.
 
 ```rust,ignore (requires-stage-2)
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 34d81f51f76..5a1612e76e3 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1183,7 +1183,13 @@ fn clean_fn_decl_from_did_and_sig<'tcx>(
     // but shouldn't change any code meaning.
     let mut output = clean_middle_ty(sig.output(), cx, None, None);
 
-    if let Some(did) = did && cx.tcx.asyncness(did).is_async() {
+    // If the return type isn't an `impl Trait`, we can safely assume that this
+    // function isn't async without needing to execute the query `asyncness` at
+    // all which gives us a noticeable performance boost.
+    if let Some(did) = did
+        && let Type::ImplTrait(_) = output
+        && cx.tcx.asyncness(did).is_async()
+    {
         output = output.sugared_async_return_type();
     }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index f5251f50b7a..1d8fa2e636e 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1604,14 +1604,16 @@ impl Type {
     ///
     /// This function will panic if the return type does not match the expected sugaring for async
     /// functions.
-    pub(crate) fn sugared_async_return_type(&self) -> Type {
-        if let Type::ImplTrait(v) = self &&
-            let [GenericBound::TraitBound(PolyTrait { trait_, .. }, _ )] = &v[..]
+    pub(crate) fn sugared_async_return_type(self) -> Type {
+        if let Type::ImplTrait(mut v) = self
+            && let Some(GenericBound::TraitBound(PolyTrait { mut trait_, .. }, _ )) = v.pop()
+            && let Some(segment) = trait_.segments.pop()
+            && let GenericArgs::AngleBracketed { mut bindings, .. } = segment.args
+            && let Some(binding) = bindings.pop()
+            && let TypeBindingKind::Equality { term } = binding.kind
+            && let Term::Type(ty) = term
         {
-            let bindings = trait_.bindings().unwrap();
-            let ret_ty = bindings[0].term();
-            let ty = ret_ty.ty().expect("unexpected constant in async fn return term");
-            ty.clone()
+            ty
         } else {
             panic!("unexpected async fn return type")
         }
@@ -2189,16 +2191,6 @@ impl Path {
             }
         })
     }
-
-    pub(crate) fn bindings(&self) -> Option<&[TypeBinding]> {
-        self.segments.last().and_then(|seg| {
-            if let GenericArgs::AngleBracketed { ref bindings, .. } = seg.args {
-                Some(&**bindings)
-            } else {
-                None
-            }
-        })
-    }
 }
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -2478,15 +2470,6 @@ pub(crate) enum TypeBindingKind {
     Constraint { bounds: Vec<GenericBound> },
 }
 
-impl TypeBinding {
-    pub(crate) fn term(&self) -> &Term {
-        match self.kind {
-            TypeBindingKind::Equality { ref term } => term,
-            _ => panic!("expected equality type binding for parenthesized generic args"),
-        }
-    }
-}
-
 /// The type, lifetime, or constant that a private type alias's parameter should be
 /// replaced with when expanding a use of that type alias.
 ///
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 0f7a3c2f952..5153dd26f4a 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -98,6 +98,8 @@ static TARGETS: &[&str] = &[
     "i686-unknown-linux-musl",
     "i686-unknown-uefi",
     "loongarch64-unknown-linux-gnu",
+    "loongarch64-unknown-none",
+    "loongarch64-unknown-none-softfloat",
     "m68k-unknown-linux-gnu",
     "csky-unknown-linux-gnuabiv2",
     "mips-unknown-linux-gnu",
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject e6aabe8b3fcf639be3a5bf68e77853bd7b3fa27
+Subproject 59596f0f31a94fde48b5aa7e945cd0b7ceca962
diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
index 367cd6bd413..ea6a9bc5657 100644
--- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
+++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs
@@ -134,15 +134,30 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
     }
 }
 
+fn stmt_might_diverge(stmt: &Stmt<'_>) -> bool {
+    match stmt.kind {
+        StmtKind::Item(..) => false,
+        _ => true,
+    }
+}
+
 impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, e: &'tcx Expr<'_>) {
         match e.kind {
             // fix #10776
             ExprKind::Block(block, ..) => match (block.stmts, block.expr) {
-                ([], Some(e)) => self.visit_expr(e),
-                ([stmt], None) => match stmt.kind {
-                    StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
-                    _ => {},
+                (stmts, Some(e)) => {
+                    if stmts.iter().all(|stmt| !stmt_might_diverge(stmt)) {
+                        self.visit_expr(e)
+                    }
+                },
+                ([first @ .., stmt], None) => {
+                    if first.iter().all(|stmt| !stmt_might_diverge(stmt)) {
+                        match stmt.kind {
+                            StmtKind::Expr(e) | StmtKind::Semi(e) => self.visit_expr(e),
+                            _ => {},
+                        }
+                    }
                 },
                 _ => {},
             },
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 82508bcdb85..eaf590f6ad7 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -228,16 +228,26 @@ pub enum PanicExpn<'a> {
 
 impl<'a> PanicExpn<'a> {
     pub fn parse(expr: &'a Expr<'a>) -> Option<Self> {
-        let ExprKind::Call(callee, [arg, rest @ ..]) = &expr.kind else {
+        let ExprKind::Call(callee, args) = &expr.kind else {
             return None;
         };
         let ExprKind::Path(QPath::Resolved(_, path)) = &callee.kind else {
             return None;
         };
-        let result = match path.segments.last().unwrap().ident.as_str() {
+        let name = path.segments.last().unwrap().ident.as_str();
+
+        // This has no argument
+        if name == "panic_cold_explicit" {
+            return Some(Self::Empty);
+        };
+
+        let [arg, rest @ ..] = args else {
+            return None;
+        };
+        let result = match name {
             "panic" if arg.span.ctxt() == expr.span.ctxt() => Self::Empty,
             "panic" | "panic_str" => Self::Str(arg),
-            "panic_display" => {
+            "panic_display" | "panic_cold_display" => {
                 let ExprKind::AddrOf(_, _, e) = &arg.kind else {
                     return None;
                 };
diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs
index f04467dc19d..9dbb4c68d13 100644
--- a/src/tools/clippy/clippy_utils/src/mir/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs
@@ -30,20 +30,26 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -
         locals.len()
     ];
 
-    traversal::ReversePostorder::new(mir, location.block).try_fold(init, |usage, (tbb, tdata)| {
-        // Give up on loops
-        if tdata.terminator().successors().any(|s| s == location.block) {
-            return None;
-        }
+    traversal::Postorder::new(&mir.basic_blocks, location.block)
+        .collect::<Vec<_>>()
+        .into_iter()
+        .rev()
+        .try_fold(init, |usage, tbb| {
+            let tdata = &mir.basic_blocks[tbb];
+
+            // Give up on loops
+            if tdata.terminator().successors().any(|s| s == location.block) {
+                return None;
+            }
 
-        let mut v = V {
-            locals,
-            location,
-            results: usage,
-        };
-        v.visit_basic_block_data(tbb, tdata);
-        Some(v.results)
-    })
+            let mut v = V {
+                locals,
+                location,
+                results: usage,
+            };
+            v.visit_basic_block_data(tbb, tdata);
+            Some(v.results)
+        })
 }
 
 struct V<'a> {
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
index 1ee048bf7f6..e1b95aa5776 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.rs
@@ -4,14 +4,18 @@
 //@no-rustfix
 use std::sync::atomic::Ordering; // #[non_exhaustive] enum
 
+fn repeat() -> ! {
+    panic!()
+}
+
 pub fn f(x: Ordering) {
     match x {
         Ordering::Relaxed => println!("relaxed"),
         Ordering::Release => println!("release"),
         Ordering::Acquire => println!("acquire"),
-        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        Ordering::AcqRel | Ordering::SeqCst => repeat(),
         #[deny(non_exhaustive_omitted_patterns)]
-        _ => panic!(),
+        _ => repeat(),
     }
 }
 
@@ -25,8 +29,8 @@ mod f {
             Ordering::Relaxed => println!("relaxed"),
             Ordering::Release => println!("release"),
             Ordering::Acquire => println!("acquire"),
-            Ordering::AcqRel | Ordering::SeqCst => panic!(),
-            _ => panic!(),
+            Ordering::AcqRel | Ordering::SeqCst => repeat(),
+            _ => repeat(),
         }
     }
 }
@@ -38,9 +42,9 @@ pub fn g(x: Ordering) {
         Ordering::Relaxed => println!("relaxed"),
         Ordering::Release => println!("release"),
         Ordering::Acquire => println!("acquire"),
-        Ordering::AcqRel | Ordering::SeqCst => panic!(),
+        Ordering::AcqRel | Ordering::SeqCst => repeat(),
         //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
-        _ => panic!(),
+        _ => repeat(),
     }
 }
 
@@ -52,9 +56,9 @@ mod g {
             Ordering::Relaxed => println!("relaxed"),
             Ordering::Release => println!("release"),
             Ordering::Acquire => println!("acquire"),
-            Ordering::AcqRel | Ordering::SeqCst => panic!(),
+            Ordering::AcqRel | Ordering::SeqCst => repeat(),
             //~^ ERROR: this match arm has an identical body to the `_` wildcard arm
-            _ => panic!(),
+            _ => repeat(),
         }
     }
 }
diff --git a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
index a039536338b..ae6b02ab1b5 100644
--- a/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
+++ b/src/tools/clippy/tests/ui/match_same_arms_non_exhaustive.stderr
@@ -1,29 +1,29 @@
 error: this match arm has an identical body to the `_` wildcard arm
-  --> $DIR/match_same_arms_non_exhaustive.rs:41:9
+  --> $DIR/match_same_arms_non_exhaustive.rs:45:9
    |
-LL |         Ordering::AcqRel | Ordering::SeqCst => panic!(),
+LL |         Ordering::AcqRel | Ordering::SeqCst => repeat(),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> $DIR/match_same_arms_non_exhaustive.rs:43:9
+  --> $DIR/match_same_arms_non_exhaustive.rs:47:9
    |
-LL |         _ => panic!(),
+LL |         _ => repeat(),
    |         ^^^^^^^^^^^^^
    = note: `-D clippy::match-same-arms` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::match_same_arms)]`
 
 error: this match arm has an identical body to the `_` wildcard arm
-  --> $DIR/match_same_arms_non_exhaustive.rs:55:13
+  --> $DIR/match_same_arms_non_exhaustive.rs:59:13
    |
-LL |             Ordering::AcqRel | Ordering::SeqCst => panic!(),
+LL |             Ordering::AcqRel | Ordering::SeqCst => repeat(),
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try removing the arm
    |
    = help: or try changing either arm body
 note: `_` wildcard arm here
-  --> $DIR/match_same_arms_non_exhaustive.rs:57:13
+  --> $DIR/match_same_arms_non_exhaustive.rs:61:13
    |
-LL |             _ => panic!(),
+LL |             _ => repeat(),
    |             ^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index ba273489eb8..0e1bf0c6c2d 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -580,6 +580,8 @@ pub struct TargetCfg {
     pub(crate) sanitizers: Vec<Sanitizer>,
     #[serde(rename = "supports-xray", default)]
     pub(crate) xray: bool,
+    #[serde(default = "default_reloc_model")]
+    pub(crate) relocation_model: String,
 }
 
 impl TargetCfg {
@@ -592,6 +594,10 @@ fn default_os() -> String {
     "none".into()
 }
 
+fn default_reloc_model() -> String {
+    "pic".into()
+}
+
 #[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)]
 #[serde(rename_all = "kebab-case")]
 pub enum Endian {
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 1113721fff6..2b7a4387ceb 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -134,6 +134,11 @@ pub(super) fn handle_needs(
             condition: config.target_cfg().dynamic_linking,
             ignore_reason: "ignored on targets without dynamic linking",
         },
+        Need {
+            name: "needs-relocation-model-pic",
+            condition: config.target_cfg().relocation_model == "pic",
+            ignore_reason: "ignored on targets without PIC relocation model",
+        },
     ];
 
     let (name, comment) = match ln.split_once([':', ' ']) {
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index d236e4bbcb4..3f11e4db327 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -409,12 +409,12 @@ dependencies = [
 
 [[package]]
 name = "libloading"
-version = "0.7.4"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
+checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb"
 dependencies = [
  "cfg-if",
- "winapi",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -947,9 +947,9 @@ dependencies = [
 
 [[package]]
 name = "ui_test"
-version = "0.21.1"
+version = "0.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "accffe020b57a6dd50014d457b5842c5a2ca73cd84f07d86d0a19c460a6509ae"
+checksum = "aaf4bf7c184b8dfc7a4d3b90df789b1eb992ee42811cd115f32a7a1eb781058d"
 dependencies = [
  "annotate-snippets",
  "anyhow",
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index 0df2c160e2f..c911a153c13 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -32,7 +32,7 @@ libc = "0.2"
 
 [target.'cfg(target_os = "linux")'.dependencies]
 libffi = "3.2.0"
-libloading = "0.7"
+libloading = "0.8"
 
 [dev-dependencies]
 colored = "2"
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 07dd52ce941..b60de8344d9 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-2ba4eb2d49e774b5fbc2a06258ac7b0f60b92b7e
+bb6c66be3793ac5c738eeac91ecdc4b99388d0b4
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index d54145dbdc7..8c90ceba1e4 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -60,7 +60,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         // The rest jumps to `ret` immediately.
-        this.emulate_intrinsic_by_name(intrinsic_name, args, dest)?;
+        this.emulate_intrinsic_by_name(intrinsic_name, instance.args, args, dest)?;
 
         trace!("{:?}", this.dump_place(dest));
         this.go_to_block(ret);
@@ -71,6 +71,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn emulate_intrinsic_by_name(
         &mut self,
         intrinsic_name: &str,
+        generic_args: ty::GenericArgsRef<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
@@ -80,7 +81,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             return this.emulate_atomic_intrinsic(name, args, dest);
         }
         if let Some(name) = intrinsic_name.strip_prefix("simd_") {
-            return this.emulate_simd_intrinsic(name, args, dest);
+            return this.emulate_simd_intrinsic(name, generic_args, args, dest);
         }
 
         match intrinsic_name {
@@ -324,7 +325,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             "fmaf32" => {
                 let [a, b, c] = check_arg_count(args)?;
-                // FIXME: Using host floats, to work around https://github.com/rust-lang/miri/issues/2468.
+                // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
                 let a = f32::from_bits(this.read_scalar(a)?.to_u32()?);
                 let b = f32::from_bits(this.read_scalar(b)?.to_u32()?);
                 let c = f32::from_bits(this.read_scalar(c)?.to_u32()?);
@@ -334,7 +335,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             "fmaf64" => {
                 let [a, b, c] = check_arg_count(args)?;
-                // FIXME: Using host floats, to work around https://github.com/rust-lang/miri/issues/2468.
+                // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
                 let a = f64::from_bits(this.read_scalar(a)?.to_u64()?);
                 let b = f64::from_bits(this.read_scalar(b)?.to_u64()?);
                 let c = f64::from_bits(this.read_scalar(c)?.to_u64()?);
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index de0c58de44f..200f37efa27 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -12,6 +12,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn emulate_simd_intrinsic(
         &mut self,
         intrinsic_name: &str,
+        generic_args: ty::GenericArgsRef<'tcx>,
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
@@ -488,6 +489,44 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     this.write_immediate(*val, &dest)?;
                 }
             }
+            "shuffle_generic" => {
+                let [left, right] = check_arg_count(args)?;
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                let index = generic_args[2]
+                    .expect_const()
+                    .eval(*this.tcx, this.param_env(), Some(this.tcx.span))
+                    .unwrap()
+                    .unwrap_branch();
+                let index_len = index.len();
+
+                assert_eq!(left_len, right_len);
+                assert_eq!(index_len as u64, dest_len);
+
+                for i in 0..dest_len {
+                    let src_index: u64 = index[usize::try_from(i).unwrap()]
+                        .unwrap_leaf()
+                        .try_to_u32()
+                        .unwrap()
+                        .into();
+                    let dest = this.project_index(&dest, i)?;
+
+                    let val = if src_index < left_len {
+                        this.read_immediate(&this.project_index(&left, src_index)?)?
+                    } else if src_index < left_len.checked_add(right_len).unwrap() {
+                        let right_idx = src_index.checked_sub(left_len).unwrap();
+                        this.read_immediate(&this.project_index(&right, right_idx)?)?
+                    } else {
+                        span_bug!(
+                            this.cur_span(),
+                            "simd_shuffle index {src_index} is out of bounds for 2 vectors of size {left_len}",
+                        );
+                    };
+                    this.write_immediate(*val, &dest)?;
+                }
+            }
             "shuffle" => {
                 let [left, right, index] = check_arg_count(args)?;
                 let (left, left_len) = this.operand_to_simd(left)?;
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs
index fbfe00e03db..7c280109cb0 100644
--- a/src/tools/miri/src/shims/x86/mod.rs
+++ b/src/tools/miri/src/shims/x86/mod.rs
@@ -9,6 +9,8 @@ use shims::foreign_items::EmulateByNameResult;
 
 mod sse;
 mod sse2;
+mod sse3;
+mod ssse3;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
@@ -88,6 +90,16 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                     this, link_name, abi, args, dest,
                 );
             }
+            name if name.starts_with("sse3.") => {
+                return sse3::EvalContextExt::emulate_x86_sse3_intrinsic(
+                    this, link_name, abi, args, dest,
+                );
+            }
+            name if name.starts_with("ssse3.") => {
+                return ssse3::EvalContextExt::emulate_x86_ssse3_intrinsic(
+                    this, link_name, abi, args, dest,
+                );
+            }
             _ => return Ok(EmulateByNameResult::NotSupported),
         }
         Ok(EmulateByNameResult::NeedsJumping)
@@ -286,3 +298,44 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>(
 
     Ok(())
 }
+
+/// Horizontaly performs `which` operation on adjacent values of
+/// `left` and `right` SIMD vectors and stores the result in `dest`.
+fn horizontal_bin_op<'tcx>(
+    this: &mut crate::MiriInterpCx<'_, 'tcx>,
+    which: mir::BinOp,
+    saturating: bool,
+    left: &OpTy<'tcx, Provenance>,
+    right: &OpTy<'tcx, Provenance>,
+    dest: &PlaceTy<'tcx, Provenance>,
+) -> InterpResult<'tcx, ()> {
+    let (left, left_len) = this.operand_to_simd(left)?;
+    let (right, right_len) = this.operand_to_simd(right)?;
+    let (dest, dest_len) = this.place_to_simd(dest)?;
+
+    assert_eq!(dest_len, left_len);
+    assert_eq!(dest_len, right_len);
+    assert_eq!(dest_len % 2, 0);
+
+    let middle = dest_len / 2;
+    for i in 0..dest_len {
+        // `i` is the index in `dest`
+        // `j` is the index of the 2-item chunk in `src`
+        let (j, src) =
+            if i < middle { (i, &left) } else { (i.checked_sub(middle).unwrap(), &right) };
+        // `base_i` is the index of the first item of the 2-item chunk in `src`
+        let base_i = j.checked_mul(2).unwrap();
+        let lhs = this.read_immediate(&this.project_index(src, base_i)?)?;
+        let rhs = this.read_immediate(&this.project_index(src, base_i.checked_add(1).unwrap())?)?;
+
+        let res = if saturating {
+            Immediate::from(this.saturating_arith(which, &lhs, &rhs)?)
+        } else {
+            *this.wrapping_binary_op(which, &lhs, &rhs)?
+        };
+
+        this.write_immediate(res, &this.project_index(&dest, i)?)?;
+    }
+
+    Ok(())
+}
diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs
index 2ca882167bf..2ef6a9b59ed 100644
--- a/src/tools/miri/src/shims/x86/sse2.rs
+++ b/src/tools/miri/src/shims/x86/sse2.rs
@@ -82,6 +82,42 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
                     this.write_immediate(*res, &dest)?;
                 }
             }
+            // Used to implement the _mm_madd_epi16 function.
+            // Multiplies packed signed 16-bit integers in `left` and `right`, producing
+            // intermediate signed 32-bit integers. Horizontally add adjacent pairs of
+            // intermediate 32-bit integers, and pack the results in `dest`.
+            "pmadd.wd" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(left_len, right_len);
+                assert_eq!(dest_len.checked_mul(2).unwrap(), left_len);
+
+                for i in 0..dest_len {
+                    let j1 = i.checked_mul(2).unwrap();
+                    let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_i16()?;
+                    let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i16()?;
+
+                    let j2 = j1.checked_add(1).unwrap();
+                    let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_i16()?;
+                    let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i16()?;
+
+                    let dest = this.project_index(&dest, i)?;
+
+                    // Multiplications are i16*i16->i32, which will not overflow.
+                    let mul1 = i32::from(left1).checked_mul(right1.into()).unwrap();
+                    let mul2 = i32::from(left2).checked_mul(right2.into()).unwrap();
+                    // However, this addition can overflow in the most extreme case
+                    // (-0x8000)*(-0x8000)+(-0x8000)*(-0x8000) = 0x80000000
+                    let res = mul1.wrapping_add(mul2);
+
+                    this.write_scalar(Scalar::from_i32(res), &dest)?;
+                }
+            }
             // Used to implement the _mm_mulhi_epi16 and _mm_mulhi_epu16 functions.
             "pmulh.w" | "pmulhu.w" => {
                 let [left, right] =
diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs
new file mode 100644
index 00000000000..f5c30a521fa
--- /dev/null
+++ b/src/tools/miri/src/shims/x86/sse3.rs
@@ -0,0 +1,90 @@
+use rustc_middle::mir;
+use rustc_span::Symbol;
+use rustc_target::abi::Align;
+use rustc_target::spec::abi::Abi;
+
+use super::horizontal_bin_op;
+use crate::*;
+use shims::foreign_items::EmulateByNameResult;
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
+    crate::MiriInterpCxExt<'mir, 'tcx>
+{
+    fn emulate_x86_sse3_intrinsic(
+        &mut self,
+        link_name: Symbol,
+        abi: Abi,
+        args: &[OpTy<'tcx, Provenance>],
+        dest: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
+        let this = self.eval_context_mut();
+        // Prefix should have already been checked.
+        let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap();
+
+        match unprefixed_name {
+            // Used to implement the _mm_addsub_ps and _mm_addsub_pd functions.
+            // Alternatingly add and subtract floating point (f32 or f64) from
+            // `left` and `right`
+            "addsub.ps" | "addsub.pd" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(dest_len, left_len);
+                assert_eq!(dest_len, right_len);
+
+                for i in 0..dest_len {
+                    let left = this.read_immediate(&this.project_index(&left, i)?)?;
+                    let right = this.read_immediate(&this.project_index(&right, i)?)?;
+                    let dest = this.project_index(&dest, i)?;
+
+                    // Even elements are subtracted and odd elements are added.
+                    let op = if i % 2 == 0 { mir::BinOp::Sub } else { mir::BinOp::Add };
+                    let res = this.wrapping_binary_op(op, &left, &right)?;
+
+                    this.write_immediate(*res, &dest)?;
+                }
+            }
+            // Used to implement the _mm_h{add,sub}_p{s,d} functions.
+            // Horizontally add/subtract adjacent floating point values
+            // in `left` and `right`.
+            "hadd.ps" | "hadd.pd" | "hsub.ps" | "hsub.pd" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let which = match unprefixed_name {
+                    "hadd.ps" | "hadd.pd" => mir::BinOp::Add,
+                    "hsub.ps" | "hsub.pd" => mir::BinOp::Sub,
+                    _ => unreachable!(),
+                };
+
+                horizontal_bin_op(this, which, /*saturating*/ false, left, right, dest)?;
+            }
+            // Used to implement the _mm_lddqu_si128 function.
+            // Reads a 128-bit vector from an unaligned pointer. This intrinsic
+            // is expected to perform better than a regular unaligned read when
+            // the data crosses a cache line, but for Miri this is just a regular
+            // unaligned read.
+            "ldu.dq" => {
+                let [src_ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let src_ptr = this.read_pointer(src_ptr)?;
+                let dest = dest.force_mplace(this)?;
+
+                this.mem_copy(
+                    src_ptr,
+                    Align::ONE,
+                    dest.ptr(),
+                    Align::ONE,
+                    dest.layout.size,
+                    /*nonoverlapping*/ true,
+                )?;
+            }
+            _ => return Ok(EmulateByNameResult::NotSupported),
+        }
+        Ok(EmulateByNameResult::NeedsJumping)
+    }
+}
diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs
new file mode 100644
index 00000000000..b0154672234
--- /dev/null
+++ b/src/tools/miri/src/shims/x86/ssse3.rs
@@ -0,0 +1,199 @@
+use rustc_middle::mir;
+use rustc_span::Symbol;
+use rustc_target::spec::abi::Abi;
+
+use super::horizontal_bin_op;
+use crate::*;
+use shims::foreign_items::EmulateByNameResult;
+
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
+    crate::MiriInterpCxExt<'mir, 'tcx>
+{
+    fn emulate_x86_ssse3_intrinsic(
+        &mut self,
+        link_name: Symbol,
+        abi: Abi,
+        args: &[OpTy<'tcx, Provenance>],
+        dest: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
+        let this = self.eval_context_mut();
+        // Prefix should have already been checked.
+        let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap();
+
+        match unprefixed_name {
+            // Used to implement the _mm_abs_epi{8,16,32} functions.
+            // Calculates the absolute value of packed 8/16/32-bit integers.
+            "pabs.b.128" | "pabs.w.128" | "pabs.d.128" => {
+                let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (op, op_len) = this.operand_to_simd(op)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(op_len, dest_len);
+
+                for i in 0..dest_len {
+                    let op = this.read_scalar(&this.project_index(&op, i)?)?;
+                    let dest = this.project_index(&dest, i)?;
+
+                    // Converting to a host "i128" works since the input is always signed.
+                    let res = op.to_int(dest.layout.size)?.unsigned_abs();
+
+                    this.write_scalar(Scalar::from_uint(res, dest.layout.size), &dest)?;
+                }
+            }
+            // Used to implement the _mm_shuffle_epi8 intrinsic.
+            // Shuffles bytes from `left` using `right` as pattern.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_shuffle_epi8
+            "pshuf.b.128" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(dest_len, left_len);
+                assert_eq!(dest_len, right_len);
+
+                for i in 0..dest_len {
+                    let right = this.read_scalar(&this.project_index(&right, i)?)?.to_u8()?;
+                    let dest = this.project_index(&dest, i)?;
+
+                    let res = if right & 0x80 == 0 {
+                        let j = right % 16; // index wraps around
+                        this.read_scalar(&this.project_index(&left, j.into())?)?
+                    } else {
+                        // If the highest bit in `right` is 1, write zero.
+                        Scalar::from_u8(0)
+                    };
+
+                    this.write_scalar(res, &dest)?;
+                }
+            }
+            // Used to implement the _mm_h{add,adds,sub}_epi{16,32} functions.
+            // Horizontally add / add with saturation / subtract adjacent 16/32-bit
+            // integer values in `left` and `right`.
+            "phadd.w.128" | "phadd.sw.128" | "phadd.d.128" | "phsub.w.128" | "phsub.sw.128"
+            | "phsub.d.128" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (which, saturating) = match unprefixed_name {
+                    "phadd.w.128" | "phadd.d.128" => (mir::BinOp::Add, false),
+                    "phadd.sw.128" => (mir::BinOp::Add, true),
+                    "phsub.w.128" | "phsub.d.128" => (mir::BinOp::Sub, false),
+                    "phsub.sw.128" => (mir::BinOp::Sub, true),
+                    _ => unreachable!(),
+                };
+
+                horizontal_bin_op(this, which, saturating, left, right, dest)?;
+            }
+            // Used to implement the _mm_maddubs_epi16 function.
+            // Multiplies packed 8-bit unsigned integers from `left` and packed
+            // signed 8-bit integers from `right` into 16-bit signed integers. Then,
+            // the saturating sum of the products with indices `2*i` and `2*i+1`
+            // produces the output at index `i`.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_maddubs_epi16
+            "pmadd.ub.sw.128" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(left_len, right_len);
+                assert_eq!(dest_len.checked_mul(2).unwrap(), left_len);
+
+                for i in 0..dest_len {
+                    let j1 = i.checked_mul(2).unwrap();
+                    let left1 = this.read_scalar(&this.project_index(&left, j1)?)?.to_u8()?;
+                    let right1 = this.read_scalar(&this.project_index(&right, j1)?)?.to_i8()?;
+
+                    let j2 = j1.checked_add(1).unwrap();
+                    let left2 = this.read_scalar(&this.project_index(&left, j2)?)?.to_u8()?;
+                    let right2 = this.read_scalar(&this.project_index(&right, j2)?)?.to_i8()?;
+
+                    let dest = this.project_index(&dest, i)?;
+
+                    // Multiplication of a u8 and an i8 into an i16 cannot overflow.
+                    let mul1 = i16::from(left1).checked_mul(right1.into()).unwrap();
+                    let mul2 = i16::from(left2).checked_mul(right2.into()).unwrap();
+                    let res = mul1.saturating_add(mul2);
+
+                    this.write_scalar(Scalar::from_i16(res), &dest)?;
+                }
+            }
+            // Used to implement the _mm_mulhrs_epi16 function.
+            // Multiplies packed 16-bit signed integer values, truncates the 32-bit
+            // product to the 18 most significant bits by right-shifting, and then
+            // divides the 18-bit value by 2 (rounding to nearest) by first adding
+            // 1 and then taking the bits `1..=16`.
+            // https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_mulhrs_epi16
+            "pmul.hr.sw.128" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(dest_len, left_len);
+                assert_eq!(dest_len, right_len);
+
+                for i in 0..dest_len {
+                    let left = this.read_scalar(&this.project_index(&left, i)?)?.to_i16()?;
+                    let right = this.read_scalar(&this.project_index(&right, i)?)?.to_i16()?;
+                    let dest = this.project_index(&dest, i)?;
+
+                    let res = (i32::from(left).checked_mul(right.into()).unwrap() >> 14)
+                        .checked_add(1)
+                        .unwrap()
+                        >> 1;
+
+                    // The result of this operation can overflow a signed 16-bit integer.
+                    // When `left` and `right` are -0x8000, the result is 0x8000.
+                    #[allow(clippy::cast_possible_truncation)]
+                    let res = res as i16;
+
+                    this.write_scalar(Scalar::from_i16(res), &dest)?;
+                }
+            }
+            // Used to implement the _mm_sign_epi{8,16,32} functions.
+            // Negates elements from `left` when the corresponding element in
+            // `right` is negative. If an element from `right` is zero, zero
+            // is writen to the corresponding output element.
+            // Basically, we multiply `left` with `right.signum()`.
+            "psign.b.128" | "psign.w.128" | "psign.d.128" => {
+                let [left, right] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+
+                let (left, left_len) = this.operand_to_simd(left)?;
+                let (right, right_len) = this.operand_to_simd(right)?;
+                let (dest, dest_len) = this.place_to_simd(dest)?;
+
+                assert_eq!(dest_len, left_len);
+                assert_eq!(dest_len, right_len);
+
+                for i in 0..dest_len {
+                    let dest = this.project_index(&dest, i)?;
+                    let left = this.read_immediate(&this.project_index(&left, i)?)?;
+                    let right = this
+                        .read_scalar(&this.project_index(&right, i)?)?
+                        .to_int(dest.layout.size)?;
+
+                    let res = this.wrapping_binary_op(
+                        mir::BinOp::Mul,
+                        &left,
+                        &ImmTy::from_int(right.signum(), dest.layout),
+                    )?;
+
+                    this.write_immediate(*res, &dest)?;
+                }
+            }
+            _ => return Ok(EmulateByNameResult::NotSupported),
+        }
+        Ok(EmulateByNameResult::NeedsJumping)
+    }
+}
diff --git a/src/tools/miri/tests/pass/float.rs b/src/tools/miri/tests/pass/float.rs
index fee5ca44ffb..70c64485fe9 100644
--- a/src/tools/miri/tests/pass/float.rs
+++ b/src/tools/miri/tests/pass/float.rs
@@ -168,6 +168,16 @@ fn basic() {
     let x: u32 = unsafe { std::mem::transmute(42.0_f32) };
     let y: f32 = unsafe { std::mem::transmute(x) };
     assert_eq(y, 42.0_f32);
+
+    // `%` sign behavior, some of this used to be buggy
+    assert!((black_box(1.0f32) % 1.0).is_sign_positive());
+    assert!((black_box(1.0f32) % -1.0).is_sign_positive());
+    assert!((black_box(-1.0f32) % 1.0).is_sign_negative());
+    assert!((black_box(-1.0f32) % -1.0).is_sign_negative());
+    assert!((black_box(1.0f64) % 1.0).is_sign_positive());
+    assert!((black_box(1.0f64) % -1.0).is_sign_positive());
+    assert!((black_box(-1.0f64) % 1.0).is_sign_negative());
+    assert!((black_box(-1.0f64) % -1.0).is_sign_negative());
 }
 
 /// Many of these test values are taken from
diff --git a/src/tools/miri/tests/pass/intrinsics-math.rs b/src/tools/miri/tests/pass/intrinsics-math.rs
index e0e4f5654d6..5f7730a3e86 100644
--- a/src/tools/miri/tests/pass/intrinsics-math.rs
+++ b/src/tools/miri/tests/pass/intrinsics-math.rs
@@ -1,4 +1,5 @@
 #![feature(float_gamma)]
+use std::{f32, f64};
 
 macro_rules! assert_approx_eq {
     ($a:expr, $b:expr) => {{
@@ -15,8 +16,7 @@ fn ldexp(a: f64, b: i32) -> f64 {
 }
 
 pub fn main() {
-    use std::f32;
-    use std::f64;
+    mul_add();
 
     assert_approx_eq!(64f32.sqrt(), 8f32);
     assert_approx_eq!(64f64.sqrt(), 8f64);
@@ -48,13 +48,6 @@ pub fn main() {
     assert_approx_eq!(8f32.log2(), 3f32);
     assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E);
 
-    assert_approx_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0);
-    assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E);
-    assert_approx_eq!(3.0f64.mul_add(2.0, 5.0), 11.0);
-    assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E);
-    assert_eq!((-3.2f32).mul_add(2.4, f32::NEG_INFINITY), f32::NEG_INFINITY);
-    assert_eq!((-3.2f64).mul_add(2.4, f64::NEG_INFINITY), f64::NEG_INFINITY);
-
     assert_approx_eq!((-1.0f32).abs(), 1.0f32);
     assert_approx_eq!(34.2f64.abs(), 34.2f64);
 
@@ -146,3 +139,19 @@ pub fn main() {
     assert_approx_eq!(val, (2.0 * f64::consts::PI.sqrt()).ln());
     assert_eq!(sign, -1);
 }
+
+fn mul_add() {
+    assert_approx_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0);
+    assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E);
+    assert_approx_eq!(3.0f64.mul_add(2.0, 5.0), 11.0);
+    assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E);
+    assert_eq!((-3.2f32).mul_add(2.4, f32::NEG_INFINITY), f32::NEG_INFINITY);
+    assert_eq!((-3.2f64).mul_add(2.4, f64::NEG_INFINITY), f64::NEG_INFINITY);
+
+    let f = f32::mul_add(
+        -0.000000000000000000000000000000000000014728589,
+        0.0000037105144,
+        0.000000000000000000000000000000000000000000055,
+    );
+    assert_eq!(f.to_bits(), f32::to_bits(-0.0));
+}
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs
index fa9df04d368..2c7665bc736 100644
--- a/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs
+++ b/src/tools/miri/tests/pass/intrinsics-x86-sse2.rs
@@ -71,6 +71,24 @@ mod tests {
         test_mm_avg_epu16();
 
         #[target_feature(enable = "sse2")]
+        unsafe fn test_mm_madd_epi16() {
+            let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+            let b = _mm_setr_epi16(9, 10, 11, 12, 13, 14, 15, 16);
+            let r = _mm_madd_epi16(a, b);
+            let e = _mm_setr_epi32(29, 81, 149, 233);
+            assert_eq_m128i(r, e);
+
+            let a =
+                _mm_setr_epi16(i16::MAX, i16::MAX, i16::MIN, i16::MIN, i16::MIN, i16::MAX, 0, 0);
+            let b =
+                _mm_setr_epi16(i16::MAX, i16::MAX, i16::MIN, i16::MIN, i16::MAX, i16::MIN, 0, 0);
+            let r = _mm_madd_epi16(a, b);
+            let e = _mm_setr_epi32(0x7FFE0002, i32::MIN, -0x7FFF0000, 0);
+            assert_eq_m128i(r, e);
+        }
+        test_mm_madd_epi16();
+
+        #[target_feature(enable = "sse2")]
         unsafe fn test_mm_mulhi_epi16() {
             let (a, b) = (_mm_set1_epi16(1000), _mm_set1_epi16(-1001));
             let r = _mm_mulhi_epi16(a, b);
diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs
new file mode 100644
index 00000000000..0805d9bc300
--- /dev/null
+++ b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs
@@ -0,0 +1,395 @@
+// Ignore everything except x86 and x86_64
+// Any additional target are added to CI should be ignored here
+// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.)
+//@ignore-target-aarch64
+//@ignore-target-arm
+//@ignore-target-avr
+//@ignore-target-s390x
+//@ignore-target-thumbv7em
+//@ignore-target-wasm32
+// SSSE3 implicitly enables SSE3
+//@compile-flags: -C target-feature=+ssse3
+
+use core::mem::transmute;
+#[cfg(target_arch = "x86")]
+use std::arch::x86::*;
+#[cfg(target_arch = "x86_64")]
+use std::arch::x86_64::*;
+
+fn main() {
+    // SSSE3 implicitly enables SSE3, still check it to be sure
+    assert!(is_x86_feature_detected!("sse3"));
+    assert!(is_x86_feature_detected!("ssse3"));
+
+    unsafe {
+        test_sse3();
+        test_ssse3();
+    }
+}
+
+#[target_feature(enable = "sse3")]
+unsafe fn test_sse3() {
+    // Mostly copied from library/stdarch/crates/core_arch/src/x86/sse3.rs
+
+    #[target_feature(enable = "sse3")]
+    unsafe fn test_mm_addsub_ps() {
+        let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0);
+        let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0);
+        let r = _mm_addsub_ps(a, b);
+        assert_eq_m128(r, _mm_setr_ps(99.0, 25.0, 0.0, -15.0));
+    }
+    test_mm_addsub_ps();
+
+    #[target_feature(enable = "sse3")]
+    unsafe fn test_mm_addsub_pd() {
+        let a = _mm_setr_pd(-1.0, 5.0);
+        let b = _mm_setr_pd(-100.0, 20.0);
+        let r = _mm_addsub_pd(a, b);
+        assert_eq_m128d(r, _mm_setr_pd(99.0, 25.0));
+    }
+    test_mm_addsub_pd();
+
+    #[target_feature(enable = "sse3")]
+    unsafe fn test_mm_hadd_ps() {
+        let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0);
+        let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0);
+        let r = _mm_hadd_ps(a, b);
+        assert_eq_m128(r, _mm_setr_ps(4.0, -10.0, -80.0, -5.0));
+    }
+    test_mm_hadd_ps();
+
+    #[target_feature(enable = "sse3")]
+    unsafe fn test_mm_hadd_pd() {
+        let a = _mm_setr_pd(-1.0, 5.0);
+        let b = _mm_setr_pd(-100.0, 20.0);
+        let r = _mm_hadd_pd(a, b);
+        assert_eq_m128d(r, _mm_setr_pd(4.0, -80.0));
+    }
+    test_mm_hadd_pd();
+
+    #[target_feature(enable = "sse3")]
+    unsafe fn test_mm_hsub_ps() {
+        let a = _mm_setr_ps(-1.0, 5.0, 0.0, -10.0);
+        let b = _mm_setr_ps(-100.0, 20.0, 0.0, -5.0);
+        let r = _mm_hsub_ps(a, b);
+        assert_eq_m128(r, _mm_setr_ps(-6.0, 10.0, -120.0, 5.0));
+    }
+    test_mm_hsub_ps();
+
+    #[target_feature(enable = "sse3")]
+    unsafe fn test_mm_hsub_pd() {
+        let a = _mm_setr_pd(-1.0, 5.0);
+        let b = _mm_setr_pd(-100.0, 20.0);
+        let r = _mm_hsub_pd(a, b);
+        assert_eq_m128d(r, _mm_setr_pd(-6.0, -120.0));
+    }
+    test_mm_hsub_pd();
+
+    #[target_feature(enable = "sse3")]
+    unsafe fn test_mm_lddqu_si128() {
+        let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+        let r = _mm_lddqu_si128(&a);
+        assert_eq_m128i(a, r);
+    }
+    test_mm_lddqu_si128();
+}
+
+#[target_feature(enable = "ssse3")]
+unsafe fn test_ssse3() {
+    // Mostly copied from library/stdarch/crates/core_arch/src/x86/ssse3.rs
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_abs_epi8() {
+        let r = _mm_abs_epi8(_mm_set1_epi8(-5));
+        assert_eq_m128i(r, _mm_set1_epi8(5));
+    }
+    test_mm_abs_epi8();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_abs_epi16() {
+        let r = _mm_abs_epi16(_mm_set1_epi16(-5));
+        assert_eq_m128i(r, _mm_set1_epi16(5));
+    }
+    test_mm_abs_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_abs_epi32() {
+        let r = _mm_abs_epi32(_mm_set1_epi32(-5));
+        assert_eq_m128i(r, _mm_set1_epi32(5));
+    }
+    test_mm_abs_epi32();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_shuffle_epi8() {
+        let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+        let b = _mm_setr_epi8(4, 128_u8 as i8, 4, 3, 24, 12, 6, 19, 12, 5, 5, 10, 4, 1, 8, 0);
+        let expected = _mm_setr_epi8(5, 0, 5, 4, 9, 13, 7, 4, 13, 6, 6, 11, 5, 2, 9, 1);
+        let r = _mm_shuffle_epi8(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test indices greater than 15 wrapping around
+        let b = _mm_add_epi8(b, _mm_set1_epi8(32));
+        let r = _mm_shuffle_epi8(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_shuffle_epi8();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_hadd_epi16() {
+        let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+        let b = _mm_setr_epi16(4, 128, 4, 3, 24, 12, 6, 19);
+        let expected = _mm_setr_epi16(3, 7, 11, 15, 132, 7, 36, 25);
+        let r = _mm_hadd_epi16(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test wrapping on overflow
+        let a = _mm_setr_epi16(i16::MAX, 1, i16::MAX, 2, i16::MAX, 3, i16::MAX, 4);
+        let b = _mm_setr_epi16(i16::MIN, -1, i16::MIN, -2, i16::MIN, -3, i16::MIN, -4);
+        let expected = _mm_setr_epi16(
+            i16::MIN,
+            i16::MIN + 1,
+            i16::MIN + 2,
+            i16::MIN + 3,
+            i16::MAX,
+            i16::MAX - 1,
+            i16::MAX - 2,
+            i16::MAX - 3,
+        );
+        let r = _mm_hadd_epi16(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_hadd_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_hadds_epi16() {
+        let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+        let b = _mm_setr_epi16(4, 128, 4, 3, 32767, 1, -32768, -1);
+        let expected = _mm_setr_epi16(3, 7, 11, 15, 132, 7, 32767, -32768);
+        let r = _mm_hadds_epi16(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test saturating on overflow
+        let a = _mm_setr_epi16(i16::MAX, 1, i16::MAX, 2, i16::MAX, 3, i16::MAX, 4);
+        let b = _mm_setr_epi16(i16::MIN, -1, i16::MIN, -2, i16::MIN, -3, i16::MIN, -4);
+        let expected = _mm_setr_epi16(
+            i16::MAX,
+            i16::MAX,
+            i16::MAX,
+            i16::MAX,
+            i16::MIN,
+            i16::MIN,
+            i16::MIN,
+            i16::MIN,
+        );
+        let r = _mm_hadds_epi16(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_hadds_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_hadd_epi32() {
+        let a = _mm_setr_epi32(1, 2, 3, 4);
+        let b = _mm_setr_epi32(4, 128, 4, 3);
+        let expected = _mm_setr_epi32(3, 7, 132, 7);
+        let r = _mm_hadd_epi32(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test wrapping on overflow
+        let a = _mm_setr_epi32(i32::MAX, 1, i32::MAX, 2);
+        let b = _mm_setr_epi32(i32::MIN, -1, i32::MIN, -2);
+        let expected = _mm_setr_epi32(i32::MIN, i32::MIN + 1, i32::MAX, i32::MAX - 1);
+        let r = _mm_hadd_epi32(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_hadd_epi32();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_hsub_epi16() {
+        let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+        let b = _mm_setr_epi16(4, 128, 4, 3, 24, 12, 6, 19);
+        let expected = _mm_setr_epi16(-1, -1, -1, -1, -124, 1, 12, -13);
+        let r = _mm_hsub_epi16(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test wrapping on overflow
+        let a = _mm_setr_epi16(i16::MAX, -1, i16::MAX, -2, i16::MAX, -3, i16::MAX, -4);
+        let b = _mm_setr_epi16(i16::MIN, 1, i16::MIN, 2, i16::MIN, 3, i16::MIN, 4);
+        let expected = _mm_setr_epi16(
+            i16::MIN,
+            i16::MIN + 1,
+            i16::MIN + 2,
+            i16::MIN + 3,
+            i16::MAX,
+            i16::MAX - 1,
+            i16::MAX - 2,
+            i16::MAX - 3,
+        );
+        let r = _mm_hsub_epi16(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_hsub_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_hsubs_epi16() {
+        let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+        let b = _mm_setr_epi16(4, 128, 4, 3, 32767, -1, -32768, 1);
+        let expected = _mm_setr_epi16(-1, -1, -1, -1, -124, 1, 32767, -32768);
+        let r = _mm_hsubs_epi16(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test saturating on overflow
+        let a = _mm_setr_epi16(i16::MAX, -1, i16::MAX, -2, i16::MAX, -3, i16::MAX, -4);
+        let b = _mm_setr_epi16(i16::MIN, 1, i16::MIN, 2, i16::MIN, 3, i16::MIN, 4);
+        let expected = _mm_setr_epi16(
+            i16::MAX,
+            i16::MAX,
+            i16::MAX,
+            i16::MAX,
+            i16::MIN,
+            i16::MIN,
+            i16::MIN,
+            i16::MIN,
+        );
+        let r = _mm_hsubs_epi16(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_hsubs_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_hsub_epi32() {
+        let a = _mm_setr_epi32(1, 2, 3, 4);
+        let b = _mm_setr_epi32(4, 128, 4, 3);
+        let expected = _mm_setr_epi32(-1, -1, -124, 1);
+        let r = _mm_hsub_epi32(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test wrapping on overflow
+        let a = _mm_setr_epi32(i32::MAX, -1, i32::MAX, -2);
+        let b = _mm_setr_epi32(i32::MIN, 1, i32::MIN, 2);
+        let expected = _mm_setr_epi32(i32::MIN, i32::MIN + 1, i32::MAX, i32::MAX - 1);
+        let r = _mm_hsub_epi32(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_hsub_epi32();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_maddubs_epi16() {
+        let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+        let b = _mm_setr_epi8(4, 63, 4, 3, 24, 12, 6, 19, 12, 5, 5, 10, 4, 1, 8, 0);
+        let expected = _mm_setr_epi16(130, 24, 192, 194, 158, 175, 66, 120);
+        let r = _mm_maddubs_epi16(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test widening and saturation
+        let a = _mm_setr_epi8(
+            u8::MAX as i8,
+            u8::MAX as i8,
+            u8::MAX as i8,
+            u8::MAX as i8,
+            u8::MAX as i8,
+            u8::MAX as i8,
+            100,
+            100,
+            0,
+            0,
+            0,
+            0,
+            0,
+            0,
+            0,
+            0,
+        );
+        let b = _mm_setr_epi8(
+            i8::MAX,
+            i8::MAX,
+            i8::MAX,
+            i8::MIN,
+            i8::MIN,
+            i8::MIN,
+            50,
+            15,
+            0,
+            0,
+            0,
+            0,
+            0,
+            0,
+            0,
+            0,
+        );
+        let expected = _mm_setr_epi16(i16::MAX, -255, i16::MIN, 6500, 0, 0, 0, 0);
+        let r = _mm_maddubs_epi16(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_maddubs_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_mulhrs_epi16() {
+        let a = _mm_setr_epi16(1, 2, 3, 4, 5, 6, 7, 8);
+        let b = _mm_setr_epi16(4, 128, 4, 3, 32767, -1, -32768, 1);
+        let expected = _mm_setr_epi16(0, 0, 0, 0, 5, 0, -7, 0);
+        let r = _mm_mulhrs_epi16(a, b);
+        assert_eq_m128i(r, expected);
+
+        // Test extreme values
+        let a = _mm_setr_epi16(i16::MAX, i16::MIN, i16::MIN, 0, 0, 0, 0, 0);
+        let b = _mm_setr_epi16(i16::MAX, i16::MIN, i16::MAX, 0, 0, 0, 0, 0);
+        let expected = _mm_setr_epi16(i16::MAX - 1, i16::MIN, -i16::MAX, 0, 0, 0, 0, 0);
+        let r = _mm_mulhrs_epi16(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_mulhrs_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_sign_epi8() {
+        let a = _mm_setr_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -14, -15, 16);
+        let b = _mm_setr_epi8(4, 63, -4, 3, 24, 12, -6, -19, 12, 5, -5, 10, 4, 1, -8, 0);
+        let expected = _mm_setr_epi8(1, 2, -3, 4, 5, 6, -7, -8, 9, 10, -11, 12, 13, -14, 15, 0);
+        let r = _mm_sign_epi8(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_sign_epi8();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_sign_epi16() {
+        let a = _mm_setr_epi16(1, 2, 3, 4, -5, -6, 7, 8);
+        let b = _mm_setr_epi16(4, 128, 0, 3, 1, -1, -2, 1);
+        let expected = _mm_setr_epi16(1, 2, 0, 4, -5, 6, -7, 8);
+        let r = _mm_sign_epi16(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_sign_epi16();
+
+    #[target_feature(enable = "ssse3")]
+    unsafe fn test_mm_sign_epi32() {
+        let a = _mm_setr_epi32(-1, 2, 3, 4);
+        let b = _mm_setr_epi32(1, -1, 1, 0);
+        let expected = _mm_setr_epi32(-1, -2, 3, 0);
+        let r = _mm_sign_epi32(a, b);
+        assert_eq_m128i(r, expected);
+    }
+    test_mm_sign_epi32();
+}
+
+#[track_caller]
+#[target_feature(enable = "sse")]
+unsafe fn assert_eq_m128(a: __m128, b: __m128) {
+    let r = _mm_cmpeq_ps(a, b);
+    if _mm_movemask_ps(r) != 0b1111 {
+        panic!("{:?} != {:?}", a, b);
+    }
+}
+
+#[track_caller]
+#[target_feature(enable = "sse2")]
+unsafe fn assert_eq_m128d(a: __m128d, b: __m128d) {
+    if _mm_movemask_pd(_mm_cmpeq_pd(a, b)) != 0b11 {
+        panic!("{:?} != {:?}", a, b);
+    }
+}
+
+#[track_caller]
+#[target_feature(enable = "sse2")]
+pub unsafe fn assert_eq_m128i(a: __m128i, b: __m128i) {
+    assert_eq!(transmute::<_, [u64; 2]>(a), transmute::<_, [u64; 2]>(b))
+}
diff --git a/src/tools/miri/tests/pass/portable-simd.rs b/src/tools/miri/tests/pass/portable-simd.rs
index ee67a65a4f9..969162e2c1e 100644
--- a/src/tools/miri/tests/pass/portable-simd.rs
+++ b/src/tools/miri/tests/pass/portable-simd.rs
@@ -1,5 +1,6 @@
 //@compile-flags: -Zmiri-strict-provenance
-#![feature(portable_simd, platform_intrinsics)]
+#![feature(portable_simd, platform_intrinsics, adt_const_params, inline_const)]
+#![allow(incomplete_features)]
 use std::simd::*;
 
 extern "platform-intrinsic" {
@@ -390,6 +391,8 @@ fn simd_intrinsics() {
         fn simd_reduce_any<T>(x: T) -> bool;
         fn simd_reduce_all<T>(x: T) -> bool;
         fn simd_select<M, T>(m: M, yes: T, no: T) -> T;
+        fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
+        fn simd_shuffle<T, IDX, U>(x: T, y: T, idx: IDX) -> U;
     }
     unsafe {
         // Make sure simd_eq returns all-1 for `true`
@@ -413,6 +416,16 @@ fn simd_intrinsics() {
             simd_select(i8x4::from_array([0, -1, -1, 0]), b, a),
             i32x4::from_array([10, 2, 10, 10])
         );
+        assert_eq!(simd_shuffle_generic::<_, i32x4, { &[3, 1, 0, 2] }>(a, b), a,);
+        assert_eq!(simd_shuffle::<_, _, i32x4>(a, b, const { [3, 1, 0, 2] }), a,);
+        assert_eq!(
+            simd_shuffle_generic::<_, i32x4, { &[7, 5, 4, 6] }>(a, b),
+            i32x4::from_array([4, 2, 1, 10]),
+        );
+        assert_eq!(
+            simd_shuffle::<_, _, i32x4>(a, b, const { [7, 5, 4, 6] }),
+            i32x4::from_array([4, 2, 1, 10]),
+        );
     }
 }
 
diff --git a/src/version b/src/version
index dc87e8af82f..7c7053aa238 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.74.0
+1.75.0
diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage-map/unreachable.cov-map
new file mode 100644
index 00000000000..495419820c1
--- /dev/null
+++ b/tests/coverage-map/unreachable.cov-map
@@ -0,0 +1,24 @@
+Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0}
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 27, 00, 49]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 15, 39) to (start + 0, 73)
+
+Function name: unreachable::unreachable_function
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 17, 1) to (start + 2, 2)
+
+Function name: unreachable::unreachable_intrinsic
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 2)
+
diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage-map/unreachable.rs
new file mode 100644
index 00000000000..6385bfa160d
--- /dev/null
+++ b/tests/coverage-map/unreachable.rs
@@ -0,0 +1,37 @@
+#![feature(core_intrinsics)]
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// <https://github.com/rust-lang/rust/issues/116171>
+// If we instrument a function for coverage, but all of its counter-increment
+// statements are removed by MIR optimizations, LLVM will think it isn't
+// instrumented and it will disappear from coverage maps and coverage reports.
+// Most MIR opts won't cause this because they tend not to remove statements
+// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+// with `TerminatorKind::Unreachable`.
+
+use std::hint::{black_box, unreachable_unchecked};
+
+static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+
+fn unreachable_function() {
+    unsafe { unreachable_unchecked() }
+}
+
+// Use an intrinsic to more reliably trigger unreachable-propagation.
+fn unreachable_intrinsic() {
+    unsafe { std::intrinsics::unreachable() }
+}
+
+#[coverage(off)]
+fn main() {
+    if black_box(false) {
+        UNREACHABLE_CLOSURE();
+    }
+    if black_box(false) {
+        unreachable_function();
+    }
+    if black_box(false) {
+        unreachable_intrinsic();
+    }
+}
diff --git a/tests/incremental/change_crate_dep_kind.rs b/tests/incremental/change_crate_dep_kind.rs
index f518266016e..b9f74340472 100644
--- a/tests/incremental/change_crate_dep_kind.rs
+++ b/tests/incremental/change_crate_dep_kind.rs
@@ -5,6 +5,7 @@
 // needs-unwind
 // revisions:cfail1 cfail2
 // compile-flags: -Z query-dep-graph -Cpanic=unwind
+// needs-unwind
 // build-pass (FIXME(62277): could be check-pass?)
 
 #![feature(panic_unwind)]
diff --git a/tests/run-coverage/unreachable.coverage b/tests/run-coverage/unreachable.coverage
new file mode 100644
index 00000000000..fa0ac9ccfa1
--- /dev/null
+++ b/tests/run-coverage/unreachable.coverage
@@ -0,0 +1,38 @@
+   LL|       |#![feature(core_intrinsics)]
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |// compile-flags: --edition=2021
+   LL|       |
+   LL|       |// <https://github.com/rust-lang/rust/issues/116171>
+   LL|       |// If we instrument a function for coverage, but all of its counter-increment
+   LL|       |// statements are removed by MIR optimizations, LLVM will think it isn't
+   LL|       |// instrumented and it will disappear from coverage maps and coverage reports.
+   LL|       |// Most MIR opts won't cause this because they tend not to remove statements
+   LL|       |// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+   LL|       |// with `TerminatorKind::Unreachable`.
+   LL|       |
+   LL|       |use std::hint::{black_box, unreachable_unchecked};
+   LL|       |
+   LL|      0|static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+   LL|       |
+   LL|      0|fn unreachable_function() {
+   LL|      0|    unsafe { unreachable_unchecked() }
+   LL|      0|}
+   LL|       |
+   LL|       |// Use an intrinsic to more reliably trigger unreachable-propagation.
+   LL|      0|fn unreachable_intrinsic() {
+   LL|      0|    unsafe { std::intrinsics::unreachable() }
+   LL|      0|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    if black_box(false) {
+   LL|       |        UNREACHABLE_CLOSURE();
+   LL|       |    }
+   LL|       |    if black_box(false) {
+   LL|       |        unreachable_function();
+   LL|       |    }
+   LL|       |    if black_box(false) {
+   LL|       |        unreachable_intrinsic();
+   LL|       |    }
+   LL|       |}
+
diff --git a/tests/run-coverage/unreachable.rs b/tests/run-coverage/unreachable.rs
new file mode 100644
index 00000000000..6385bfa160d
--- /dev/null
+++ b/tests/run-coverage/unreachable.rs
@@ -0,0 +1,37 @@
+#![feature(core_intrinsics)]
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// <https://github.com/rust-lang/rust/issues/116171>
+// If we instrument a function for coverage, but all of its counter-increment
+// statements are removed by MIR optimizations, LLVM will think it isn't
+// instrumented and it will disappear from coverage maps and coverage reports.
+// Most MIR opts won't cause this because they tend not to remove statements
+// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+// with `TerminatorKind::Unreachable`.
+
+use std::hint::{black_box, unreachable_unchecked};
+
+static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+
+fn unreachable_function() {
+    unsafe { unreachable_unchecked() }
+}
+
+// Use an intrinsic to more reliably trigger unreachable-propagation.
+fn unreachable_intrinsic() {
+    unsafe { std::intrinsics::unreachable() }
+}
+
+#[coverage(off)]
+fn main() {
+    if black_box(false) {
+        UNREACHABLE_CLOSURE();
+    }
+    if black_box(false) {
+        unreachable_function();
+    }
+    if black_box(false) {
+        unreachable_intrinsic();
+    }
+}
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index 249e8176283..1f049b1785a 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -1,16 +1,174 @@
 // check-pass
+// revisions: host
+// revisions: arm
+//[arm] compile-flags: --target arm-unknown-linux-gnueabi
+//[arm] needs-llvm-components: arm
+// revisions: aarch64
+//[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
+//[aarch64] needs-llvm-components: aarch64
+// revisions: s390x
+//[s390x] compile-flags: --target s390x-unknown-linux-gnu
+//[s390x] needs-llvm-components: systemz
+// revisions: mips
+//[mips] compile-flags: --target mips-unknown-linux-gnu
+//[mips] needs-llvm-components: mips
+// revisions: mips64
+//[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
+//[mips64] needs-llvm-components: mips
+// revisions: sparc
+//[sparc] compile-flags: --target sparc-unknown-linux-gnu
+//[sparc] needs-llvm-components: sparc
+// revisions: sparc64
+//[sparc64] compile-flags: --target sparc64-unknown-linux-gnu
+//[sparc64] needs-llvm-components: sparc
+// revisions: powerpc64
+//[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
+//[powerpc64] needs-llvm-components: powerpc
+// revisions: riscv
+//[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu
+//[riscv] needs-llvm-components: riscv
+// revisions: loongarch64
+//[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
+//[loongarch64] needs-llvm-components: loongarch
+// revisions: wasm
+//[wasm] compile-flags: --target wasm32-unknown-unknown
+//[wasm] needs-llvm-components: webassembly
+// revisions: wasi
+//[wasi] compile-flags: --target wasm32-wasi
+//[wasi] needs-llvm-components: webassembly
+// revisions: nvptx64
+//[nvptx64] compile-flags: --target nvptx64-nvidia-cuda
+//[nvptx64] needs-llvm-components: nvptx
 #![feature(rustc_attrs, unsized_fn_params, transparent_unions)]
+#![cfg_attr(not(host), feature(no_core, lang_items), no_std, no_core)]
 #![allow(unused, improper_ctypes_definitions, internal_features)]
-use std::marker::PhantomData;
-use std::mem::ManuallyDrop;
-use std::num::NonZeroI32;
-use std::ptr::NonNull;
 
-// FIXME: a bunch of targets are broken in various ways.
+// FIXME: some targets are broken in various ways.
 // Hence there are `cfg` throughout this test to disable parts of it on those targets.
 // sparc64: https://github.com/rust-lang/rust/issues/115336
 // mips64: https://github.com/rust-lang/rust/issues/115404
 
+#[cfg(host)]
+use std::{
+    any::Any, marker::PhantomData, mem::ManuallyDrop, num::NonZeroI32, ptr::NonNull, rc::Rc,
+    sync::Arc,
+};
+
+/// To work cross-target this test must be no_core.
+/// This little prelude supplies what we need.
+#[cfg(not(host))]
+mod prelude {
+    #[lang = "sized"]
+    pub trait Sized {}
+
+    #[lang = "receiver"]
+    pub trait Receiver {}
+    impl<T: ?Sized> Receiver for &T {}
+    impl<T: ?Sized> Receiver for &mut T {}
+
+    #[lang = "copy"]
+    pub trait Copy: Sized {}
+    impl Copy for i32 {}
+    impl Copy for f32 {}
+    impl<T: ?Sized> Copy for &T {}
+    impl<T: ?Sized> Copy for *const T {}
+    impl<T: ?Sized> Copy for *mut T {}
+
+    #[lang = "clone"]
+    pub trait Clone: Sized {
+        fn clone(&self) -> Self;
+    }
+
+    #[lang = "phantom_data"]
+    pub struct PhantomData<T: ?Sized>;
+    impl<T: ?Sized> Copy for PhantomData<T> {}
+
+    #[lang = "unsafe_cell"]
+    #[repr(transparent)]
+    pub struct UnsafeCell<T: ?Sized> {
+        value: T,
+    }
+
+    pub trait Any: 'static {}
+
+    pub enum Option<T> {
+        None,
+        Some(T),
+    }
+    impl<T: Copy> Copy for Option<T> {}
+
+    pub enum Result<T, E> {
+        Ok(T),
+        Err(E),
+    }
+    impl<T: Copy, E: Copy> Copy for Result<T, E> {}
+
+    #[lang = "manually_drop"]
+    #[repr(transparent)]
+    pub struct ManuallyDrop<T: ?Sized> {
+        value: T,
+    }
+    impl<T: Copy + ?Sized> Copy for ManuallyDrop<T> {}
+
+    #[repr(transparent)]
+    #[rustc_layout_scalar_valid_range_start(1)]
+    #[rustc_nonnull_optimization_guaranteed]
+    pub struct NonNull<T: ?Sized> {
+        pointer: *const T,
+    }
+    impl<T: ?Sized> Copy for NonNull<T> {}
+
+    #[repr(transparent)]
+    #[rustc_layout_scalar_valid_range_start(1)]
+    #[rustc_nonnull_optimization_guaranteed]
+    pub struct NonZeroI32(i32);
+
+    // This just stands in for a non-trivial type.
+    pub struct Vec<T> {
+        ptr: NonNull<T>,
+        cap: usize,
+        len: usize,
+    }
+
+    pub struct Unique<T: ?Sized> {
+        pub pointer: NonNull<T>,
+        pub _marker: PhantomData<T>,
+    }
+
+    pub struct Global;
+
+    #[lang = "owned_box"]
+    pub struct Box<T: ?Sized, A = Global>(Unique<T>, A);
+
+    #[repr(C)]
+    struct RcBox<T: ?Sized> {
+        strong: UnsafeCell<usize>,
+        weak: UnsafeCell<usize>,
+        value: T,
+    }
+    pub struct Rc<T: ?Sized, A = Global> {
+        ptr: NonNull<RcBox<T>>,
+        phantom: PhantomData<RcBox<T>>,
+        alloc: A,
+    }
+
+    #[repr(C, align(8))]
+    struct AtomicUsize(usize);
+    #[repr(C)]
+    struct ArcInner<T: ?Sized> {
+        strong: AtomicUsize,
+        weak: AtomicUsize,
+        data: T,
+    }
+    pub struct Arc<T: ?Sized, A = Global> {
+        ptr: NonNull<ArcInner<T>>,
+        phantom: PhantomData<ArcInner<T>>,
+        alloc: A,
+    }
+}
+#[cfg(not(host))]
+use prelude::*;
+
 macro_rules! assert_abi_compatible {
     ($name:ident, $t1:ty, $t2:ty) => {
         mod $name {
@@ -26,8 +184,13 @@ macro_rules! assert_abi_compatible {
     };
 }
 
-#[derive(Copy, Clone)]
 struct Zst;
+impl Copy for Zst {}
+impl Clone for Zst {
+    fn clone(&self) -> Self {
+        Zst
+    }
+}
 
 #[repr(C)]
 struct ReprC1<T: ?Sized>(T);
@@ -85,8 +248,8 @@ test_abi_compatible!(nonzero_int, NonZeroI32, i32);
 
 // `DispatchFromDyn` relies on ABI compatibility.
 // This is interesting since these types are not `repr(transparent)`.
-test_abi_compatible!(rc, std::rc::Rc<i32>, *mut i32);
-test_abi_compatible!(arc, std::sync::Arc<i32>, *mut i32);
+test_abi_compatible!(rc, Rc<i32>, *mut i32);
+test_abi_compatible!(arc, Arc<i32>, *mut i32);
 
 // `repr(transparent)` compatibility.
 #[repr(transparent)]
@@ -160,7 +323,7 @@ mod unsized_ {
     use super::*;
     test_transparent_unsized!(str_, str);
     test_transparent_unsized!(slice, [u8]);
-    test_transparent_unsized!(dyn_trait, dyn std::any::Any);
+    test_transparent_unsized!(dyn_trait, dyn Any);
 }
 
 // RFC 3391 <https://rust-lang.github.io/rfcs/3391-result_ffi_guarantees.html>.
@@ -185,7 +348,7 @@ test_nonnull!(ref_unsized, &[i32]);
 test_nonnull!(mut_unsized, &mut [i32]);
 test_nonnull!(fn_, fn());
 test_nonnull!(nonnull, NonNull<i32>);
-test_nonnull!(nonnull_unsized, NonNull<dyn std::fmt::Debug>);
+test_nonnull!(nonnull_unsized, NonNull<dyn Any>);
 test_nonnull!(non_zero, NonZeroI32);
 
 fn main() {}
diff --git a/tests/ui/abi/relocation_model_pic.rs b/tests/ui/abi/relocation_model_pic.rs
index 0cfc44cd09d..cca2e8db74d 100644
--- a/tests/ui/abi/relocation_model_pic.rs
+++ b/tests/ui/abi/relocation_model_pic.rs
@@ -1,7 +1,6 @@
 // run-pass
 // compile-flags: -C relocation-model=pic
-// ignore-emscripten no pic
-// ignore-wasm
+// needs-relocation-model-pic
 
 #![feature(cfg_relocation_model)]
 
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
index 38a80f8b670..751959f55bb 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames-2.rs
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
@@ -2,6 +2,7 @@
 // run-fail
 // check-run-results
 // exec-env:RUST_BACKTRACE=1
+// needs-unwind
 // ignore-android FIXME #17520
 // ignore-wasm no panic support
 // ignore-openbsd no support for libbacktrace without filename
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
index 2b648a0cad2..664ebaa4c51 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:56:5:
+thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:57:5:
 debug!!!
 stack backtrace:
    0: std::panicking::begin_panic
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs
index c872084f033..134e13233da 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames.rs
+++ b/tests/ui/panics/short-ice-remove-middle-frames.rs
@@ -2,6 +2,7 @@
 // run-fail
 // check-run-results
 // exec-env:RUST_BACKTRACE=1
+// needs-unwind
 // ignore-android FIXME #17520
 // ignore-wasm no panic support
 // ignore-openbsd no support for libbacktrace without filename
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
index 5b372684096..bc252fde1f6 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
+++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:52:5:
+thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:53:5:
 debug!!!
 stack backtrace:
    0: std::panicking::begin_panic
diff --git a/tests/ui/resolve/issue-116164.rs b/tests/ui/resolve/issue-116164.rs
new file mode 100644
index 00000000000..d30c8f514b3
--- /dev/null
+++ b/tests/ui/resolve/issue-116164.rs
@@ -0,0 +1,19 @@
+#![allow(unused_imports)]
+
+mod inner {
+    pub enum Example {
+        ExOne,
+    }
+}
+
+mod reexports {
+    pub use crate::inner::Example as _;
+}
+
+use crate::reexports::*;
+//~^ SUGGESTION: use inner::Example::ExOne
+
+fn main() {
+    ExOne;
+    //~^ ERROR: cannot find value `ExOne` in this scope
+}
diff --git a/tests/ui/resolve/issue-116164.stderr b/tests/ui/resolve/issue-116164.stderr
new file mode 100644
index 00000000000..5820a189fd5
--- /dev/null
+++ b/tests/ui/resolve/issue-116164.stderr
@@ -0,0 +1,14 @@
+error[E0425]: cannot find value `ExOne` in this scope
+  --> $DIR/issue-116164.rs:17:5
+   |
+LL |     ExOne;
+   |     ^^^^^ not found in this scope
+   |
+help: consider importing this unit variant
+   |
+LL + use inner::Example::ExOne;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/simd/intrinsic/generic-elements.rs b/tests/ui/simd/intrinsic/generic-elements.rs
index 0ff2203ec72..6ba93e46f75 100644
--- a/tests/ui/simd/intrinsic/generic-elements.rs
+++ b/tests/ui/simd/intrinsic/generic-elements.rs
@@ -1,6 +1,7 @@
 // build-fail
 
-#![feature(repr_simd, platform_intrinsics, rustc_attrs)]
+#![feature(repr_simd, platform_intrinsics, rustc_attrs, adt_const_params)]
+#![allow(incomplete_features)]
 
 #[repr(simd)]
 #[derive(Copy, Clone)]
@@ -35,6 +36,7 @@ extern "platform-intrinsic" {
     fn simd_extract<T, E>(x: T, idx: u32) -> E;
 
     fn simd_shuffle<T, I, U>(x: T, y: T, idx: I) -> U;
+    fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
 }
 
 fn main() {
@@ -71,5 +73,29 @@ fn main() {
         //~^ ERROR expected return type of length 4, found `i32x8` with length 8
         simd_shuffle::<_, _, i32x2>(x, x, IDX8);
         //~^ ERROR expected return type of length 8, found `i32x2` with length 2
+
+        const I2: &[u32] = &[0; 2];
+        simd_shuffle_generic::<i32, i32, I2>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        const I4: &[u32] = &[0; 4];
+        simd_shuffle_generic::<i32, i32, I4>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+        const I8: &[u32] = &[0; 8];
+        simd_shuffle_generic::<i32, i32, I8>(0, 0);
+        //~^ ERROR expected SIMD input type, found non-SIMD `i32`
+
+        simd_shuffle_generic::<_, f32x2, I2>(x, x);
+//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
+        simd_shuffle_generic::<_, f32x4, I4>(x, x);
+//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
+        simd_shuffle_generic::<_, f32x8, I8>(x, x);
+//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
+
+        simd_shuffle_generic::<_, i32x8, I2>(x, x);
+        //~^ ERROR expected return type of length 2, found `i32x8` with length 8
+        simd_shuffle_generic::<_, i32x8, I4>(x, x);
+        //~^ ERROR expected return type of length 4, found `i32x8` with length 8
+        simd_shuffle_generic::<_, i32x2, I8>(x, x);
+        //~^ ERROR expected return type of length 8, found `i32x2` with length 2
     }
 }
diff --git a/tests/ui/simd/intrinsic/generic-elements.stderr b/tests/ui/simd/intrinsic/generic-elements.stderr
index 115d9d4b3f3..26e01344939 100644
--- a/tests/ui/simd/intrinsic/generic-elements.stderr
+++ b/tests/ui/simd/intrinsic/generic-elements.stderr
@@ -1,75 +1,129 @@
 error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:44:9
+  --> $DIR/generic-elements.rs:46:9
    |
 LL |         simd_insert(0, 0, 0);
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64`
-  --> $DIR/generic-elements.rs:46:9
+  --> $DIR/generic-elements.rs:48:9
    |
 LL |         simd_insert(x, 0, 1.0);
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32`
-  --> $DIR/generic-elements.rs:48:9
+  --> $DIR/generic-elements.rs:50:9
    |
 LL |         simd_extract::<_, f32>(x, 0);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:52:9
+  --> $DIR/generic-elements.rs:54:9
    |
 LL |         simd_shuffle::<i32, _, i32>(0, 0, IDX2);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:55:9
+  --> $DIR/generic-elements.rs:57:9
    |
 LL |         simd_shuffle::<i32, _, i32>(0, 0, IDX4);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected SIMD input type, found non-SIMD `i32`
-  --> $DIR/generic-elements.rs:58:9
+  --> $DIR/generic-elements.rs:60:9
    |
 LL |         simd_shuffle::<i32, _, i32>(0, 0, IDX8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
-  --> $DIR/generic-elements.rs:61:9
+  --> $DIR/generic-elements.rs:63:9
    |
 LL |         simd_shuffle::<_, _, f32x2>(x, x, IDX2);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
-  --> $DIR/generic-elements.rs:63:9
+  --> $DIR/generic-elements.rs:65:9
    |
 LL |         simd_shuffle::<_, _, f32x4>(x, x, IDX4);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
-  --> $DIR/generic-elements.rs:65:9
+  --> $DIR/generic-elements.rs:67:9
    |
 LL |         simd_shuffle::<_, _, f32x8>(x, x, IDX8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 2, found `i32x8` with length 8
-  --> $DIR/generic-elements.rs:68:9
+  --> $DIR/generic-elements.rs:70:9
    |
 LL |         simd_shuffle::<_, _, i32x8>(x, x, IDX2);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 4, found `i32x8` with length 8
-  --> $DIR/generic-elements.rs:70:9
+  --> $DIR/generic-elements.rs:72:9
    |
 LL |         simd_shuffle::<_, _, i32x8>(x, x, IDX4);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: expected return type of length 8, found `i32x2` with length 2
-  --> $DIR/generic-elements.rs:72:9
+  --> $DIR/generic-elements.rs:74:9
    |
 LL |         simd_shuffle::<_, _, i32x2>(x, x, IDX8);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/generic-elements.rs:78:9
+   |
+LL |         simd_shuffle_generic::<i32, i32, I2>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/generic-elements.rs:81:9
+   |
+LL |         simd_shuffle_generic::<i32, i32, I4>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected SIMD input type, found non-SIMD `i32`
+  --> $DIR/generic-elements.rs:84:9
+   |
+LL |         simd_shuffle_generic::<i32, i32, I8>(0, 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
+  --> $DIR/generic-elements.rs:87:9
+   |
+LL |         simd_shuffle_generic::<_, f32x2, I2>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
+  --> $DIR/generic-elements.rs:89:9
+   |
+LL |         simd_shuffle_generic::<_, f32x4, I4>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
+  --> $DIR/generic-elements.rs:91:9
+   |
+LL |         simd_shuffle_generic::<_, f32x8, I8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 2, found `i32x8` with length 8
+  --> $DIR/generic-elements.rs:94:9
+   |
+LL |         simd_shuffle_generic::<_, i32x8, I2>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 4, found `i32x8` with length 8
+  --> $DIR/generic-elements.rs:96:9
+   |
+LL |         simd_shuffle_generic::<_, i32x8, I4>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0511]: invalid monomorphization of `simd_shuffle_generic` intrinsic: expected return type of length 8, found `i32x2` with length 2
+  --> $DIR/generic-elements.rs:98:9
+   |
+LL |         simd_shuffle_generic::<_, i32x2, I8>(x, x);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 21 previous errors
 
 For more information about this error, try `rustc --explain E0511`.
diff --git a/tests/ui/simd/monomorphize-shuffle-index.generic.stderr b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr
new file mode 100644
index 00000000000..fc66b195674
--- /dev/null
+++ b/tests/ui/simd/monomorphize-shuffle-index.generic.stderr
@@ -0,0 +1,12 @@
+error: overly complex generic constant
+  --> $DIR/monomorphize-shuffle-index.rs:29:45
+   |
+LL |         return simd_shuffle_generic::<_, _, { &Self::I }>(a, b);
+   |                                             ^^--------^^
+   |                                               |
+   |                                               pointer casts are not allowed in generic constants
+   |
+   = help: consider moving this anonymous constant into a `const` function
+
+error: aborting due to previous error
+
diff --git a/tests/ui/simd/monomorphize-shuffle-index.rs b/tests/ui/simd/monomorphize-shuffle-index.rs
index 2467baa08b0..db7953f06dd 100644
--- a/tests/ui/simd/monomorphize-shuffle-index.rs
+++ b/tests/ui/simd/monomorphize-shuffle-index.rs
@@ -1,8 +1,14 @@
-//run-pass
-#![feature(repr_simd, platform_intrinsics)]
+//[old]run-pass
+//[generic_with_fn]run-pass
+// revisions: old generic generic_with_fn
+#![feature(repr_simd, platform_intrinsics, adt_const_params, generic_const_exprs)]
+#![allow(incomplete_features)]
 
 extern "platform-intrinsic" {
+    #[cfg(old)]
     fn simd_shuffle<T, I, U>(a: T, b: T, i: I) -> U;
+    #[cfg(any(generic, generic_with_fn))]
+    fn simd_shuffle_generic<T, U, const I: &'static [u32]>(a: T, b: T) -> U;
 }
 
 #[derive(Copy, Clone)]
@@ -11,12 +17,24 @@ 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)
+    const J: &'static [u32] = &Self::I;
+
+    unsafe fn shuffle<T, const M: usize>(&self, a: Simd<T, M>, b: Simd<T, M>) -> Simd<T, N>
+    where
+        Thing<{ Self::J }>:,
+    {
+        #[cfg(old)]
+        return simd_shuffle(a, b, Self::I);
+        #[cfg(generic)]
+        return simd_shuffle_generic::<_, _, { &Self::I }>(a, b);
+        //[generic]~^ overly complex generic constant
+        #[cfg(generic_with_fn)]
+        return simd_shuffle_generic::<_, _, { Self::J }>(a, b);
     }
 }
 
+struct Thing<const X: &'static [u32]>;
+
 fn main() {
     struct I1;
     impl Shuffle<4> for I1 {
diff --git a/tests/ui/suggestions/auxiliary/extern-issue-98562.rs b/tests/ui/suggestions/auxiliary/extern-issue-98562.rs
new file mode 100644
index 00000000000..948e40549c6
--- /dev/null
+++ b/tests/ui/suggestions/auxiliary/extern-issue-98562.rs
@@ -0,0 +1,26 @@
+pub trait TraitE {
+    type I3;
+}
+
+pub trait TraitD {
+    type I3;
+}
+
+pub trait TraitC {
+    type I1;
+    type I2;
+}
+
+pub trait TraitB {
+    type Item;
+}
+
+pub trait TraitA<G1, G2, G3> {
+    fn baz<
+        U: TraitC<I1 = G1, I2 = G2> + TraitD<I3 = G3> + TraitE,
+        V: TraitD<I3 = G1>
+    >(_: U, _: V) -> Self
+    where
+        U: TraitB,
+        <U as TraitB>::Item: Copy;
+}
diff --git a/tests/ui/suggestions/issue-98562.rs b/tests/ui/suggestions/issue-98562.rs
new file mode 100644
index 00000000000..de04050d593
--- /dev/null
+++ b/tests/ui/suggestions/issue-98562.rs
@@ -0,0 +1,12 @@
+// aux-build:extern-issue-98562.rs
+
+extern crate extern_issue_98562;
+use extern_issue_98562::TraitA;
+
+struct X;
+impl TraitA<u8, u16, u32> for X {
+    //~^ ERROR not all trait items implemented
+}
+//~^ HELP implement the missing item: `fn baz<U: TraitC<I1 = u8, I2 = u16> + TraitD<I3 = u32>, V: TraitD<I3 = u8>>(_: U, _: V) -> Self where U: TraitE, U: TraitB, <U as TraitB>::Item: Copy { todo!() }`
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-98562.stderr b/tests/ui/suggestions/issue-98562.stderr
new file mode 100644
index 00000000000..7897fa441a2
--- /dev/null
+++ b/tests/ui/suggestions/issue-98562.stderr
@@ -0,0 +1,11 @@
+error[E0046]: not all trait items implemented, missing: `baz`
+  --> $DIR/issue-98562.rs:7:1
+   |
+LL | impl TraitA<u8, u16, u32> for X {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `baz` in implementation
+   |
+   = help: implement the missing item: `fn baz<U: TraitC<I1 = u8, I2 = u16> + TraitD<I3 = u32>, V: TraitD<I3 = u8>>(_: U, _: V) -> Self where U: TraitE, U: TraitB, <U as TraitB>::Item: Copy { todo!() }`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/suggestions/missing-assoc-fn.stderr b/tests/ui/suggestions/missing-assoc-fn.stderr
index 77fa9562878..84cb6e98553 100644
--- a/tests/ui/suggestions/missing-assoc-fn.stderr
+++ b/tests/ui/suggestions/missing-assoc-fn.stderr
@@ -28,7 +28,7 @@ error[E0046]: not all trait items implemented, missing: `from_iter`
 LL | impl FromIterator<()> for X {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `from_iter` in implementation
    |
-   = help: implement the missing item: `fn from_iter<T>(_: T) -> Self where T: IntoIterator, std::iter::IntoIterator::Item = () { todo!() }`
+   = help: implement the missing item: `fn from_iter<T: IntoIterator<Item = ()>>(_: T) -> Self { todo!() }`
 
 error: aborting due to 3 previous errors
 
diff --git a/x b/x
index d967988e1c4..ef3eb8b04b4 100755
--- a/x
+++ b/x
@@ -8,7 +8,7 @@
 set -eu
 
 # syntax check
-sh -n $0
+sh -n "$0"
 
 realpath() {
     if [ -d "$1" ]; then