about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-06-09 18:54:46 +0000
committerbors <bors@rust-lang.org>2024-06-09 18:54:46 +0000
commit503dfcf4e03089cf0c06d10fc69b5477a2f766ef (patch)
treed9629c6f0d6e25fd85886f1f957c68190e7253d3
parent65d1a73aabc03c7f94633bf00eee1b5548c28c14 (diff)
parenta8cba36cbfcced6c1663161bfdd79bce43916fba (diff)
downloadrust-503dfcf4e03089cf0c06d10fc69b5477a2f766ef.tar.gz
rust-503dfcf4e03089cf0c06d10fc69b5477a2f766ef.zip
Auto merge of #126202 - jieyouxu:rollup-2ixnizz, r=jieyouxu
Rollup of 6 pull requests

Successful merges:

 - #125041 (Enable GVN for `AggregateKind::RawPtr`)
 - #125253 (Add `FRAC_1_SQRT_2PI` constant to f16/f32/f64/f128)
 - #125465 (bootstrap: vendor crates required by opt-dist to collect profiles )
 - #125470 (Add release notes for 1.79.0)
 - #125963 (Remove hard-coded hashes from codegen tests)
 - #126188 (Fix documentation for `impl_common_helpers` in `run-make-support`)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--RELEASES.md128
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs99
-rw-r--r--library/core/src/num/f128.rs7
-rw-r--r--library/core/src/num/f16.rs6
-rw-r--r--library/core/src/num/f32.rs5
-rw-r--r--library/core/src/num/f64.rs5
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs15
-rw-r--r--src/tools/build_helper/README.md1
-rw-r--r--src/tools/build_helper/src/lib.rs25
-rw-r--r--src/tools/opt-dist/src/training.rs22
-rw-r--r--src/tools/run-make-support/src/lib.rs20
-rw-r--r--src/tools/tidy/src/deps.rs36
-rw-r--r--src/tools/tidy/src/extdeps.rs6
-rw-r--r--tests/assembly/asm/global_asm.rs4
-rw-r--r--tests/codegen/consts.rs4
-rw-r--r--tests/codegen/pattern_type_symbols.rs4
-rw-r--r--tests/codegen/virtual-function-elimination.rs4
-rw-r--r--tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff60
-rw-r--r--tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff60
-rw-r--r--tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff32
-rw-r--r--tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff32
-rw-r--r--tests/mir-opt/gvn.rs40
-rw-r--r--tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff48
-rw-r--r--tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff48
-rw-r--r--tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff51
-rw-r--r--tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff51
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir10
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir10
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir2
30 files changed, 767 insertions, 70 deletions
diff --git a/RELEASES.md b/RELEASES.md
index 3080f03c721..c1311ab14c5 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,131 @@
+Version 1.79.0 (2024-06-13)
+==========================
+
+<a id="1.79.0-Language"></a>
+
+Language
+--------
+- [Stabilize inline `const {}` expressions.](https://github.com/rust-lang/rust/pull/104087/)
+- [Prevent opaque types being instantiated twice with different regions within the same function.](https://github.com/rust-lang/rust/pull/116935/)
+- [Stabilize WebAssembly target features that are in phase 4 and 5.](https://github.com/rust-lang/rust/pull/117457/)
+- [Add the `redundant_lifetimes` lint to detect lifetimes which are semantically redundant.](https://github.com/rust-lang/rust/pull/118391/)
+- [Stabilize the `unnameable_types` lint for public types that can't be named.](https://github.com/rust-lang/rust/pull/120144/)
+- [Enable debuginfo in macros, and stabilize `-C collapse-macro-debuginfo` and `#[collapse_debuginfo]`.](https://github.com/rust-lang/rust/pull/120845/)
+- [Propagate temporary lifetime extension into `if` and `match` expressions.](https://github.com/rust-lang/rust/pull/121346/)
+- [Restrict promotion of `const fn` calls.](https://github.com/rust-lang/rust/pull/121557/)
+- [Warn against refining impls of crate-private traits with `refining_impl_trait` lint.](https://github.com/rust-lang/rust/pull/121720/)
+- [Stabilize associated type bounds (RFC 2289).](https://github.com/rust-lang/rust/pull/122055/)
+- [Stabilize importing `main` from other modules or crates.](https://github.com/rust-lang/rust/pull/122060/)
+- [Check return types of function types for well-formedness](https://github.com/rust-lang/rust/pull/115538)
+- [Rework `impl Trait` lifetime inference](https://github.com/rust-lang/rust/pull/116891/)
+- [Change inductive trait solver cycles to be ambiguous](https://github.com/rust-lang/rust/pull/122791)
+
+<a id="1.79.0-Compiler"></a>
+
+Compiler
+--------
+- [Define `-C strip` to only affect binaries, not artifacts like `.pdb`.](https://github.com/rust-lang/rust/pull/115120/)
+- [Stabilize `-Crelro-level` for controlling runtime link hardening.](https://github.com/rust-lang/rust/pull/121694/)
+- [Stabilize checking of `cfg` names and values at compile-time with `--check-cfg`.](https://github.com/rust-lang/rust/pull/123501/)
+  *Note that this only stabilizes the compiler part, the Cargo part is still unstable in this release.*
+- [Add `aarch64-apple-visionos` and `aarch64-apple-visionos-sim` tier 3 targets.](https://github.com/rust-lang/rust/pull/121419/)
+- [Add `riscv32ima-unknown-none-elf` tier 3 target.](https://github.com/rust-lang/rust/pull/122696/)
+- [Promote several Windows targets to tier 2](https://github.com/rust-lang/rust/pull/121712): `aarch64-pc-windows-gnullvm`, `i686-pc-windows-gnullvm`, and `x86_64-pc-windows-gnullvm`.
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.79.0-Libraries"></a>
+
+Libraries
+---------
+
+- [Implement `FromIterator` for `(impl Default + Extend, impl Default + Extend)`.](https://github.com/rust-lang/rust/pull/107462/)
+- [Implement `{Div,Rem}Assign<NonZero<X>>` on `X`.](https://github.com/rust-lang/rust/pull/121952/)
+- [Document overrides of `clone_from()` in core/std.](https://github.com/rust-lang/rust/pull/122201/)
+- [Link MSVC default lib in core.](https://github.com/rust-lang/rust/pull/122268/)
+- [Caution against using `transmute` between pointers and integers.](https://github.com/rust-lang/rust/pull/122379/)
+- [Enable frame pointers for the standard library.](https://github.com/rust-lang/rust/pull/122646/)
+
+<a id="1.79.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`{integer}::unchecked_add`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.unchecked_add)
+- [`{integer}::unchecked_mul`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.unchecked_mul)
+- [`{integer}::unchecked_sub`](https://doc.rust-lang.org/stable/core/primitive.i32.html#method.unchecked_sub)
+- [`<[T]>::split_at_unchecked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_unchecked)
+- [`<[T]>::split_at_mut_unchecked`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.split_at_mut_unchecked)
+- [`<[u8]>::utf8_chunks`](https://doc.rust-lang.org/stable/core/primitive.slice.html#method.utf8_chunks)
+- [`str::Utf8Chunks`](https://doc.rust-lang.org/stable/core/str/struct.Utf8Chunks.html)
+- [`str::Utf8Chunk`](https://doc.rust-lang.org/stable/core/str/struct.Utf8Chunk.html)
+- [`<*const T>::is_aligned`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_aligned)
+- [`<*mut T>::is_aligned`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_aligned-1)
+- [`NonNull::is_aligned`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.is_aligned)
+- [`<*const [T]>::len`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.len)
+- [`<*mut [T]>::len`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.len-1)
+- [`<*const [T]>::is_empty`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_empty)
+- [`<*mut [T]>::is_empty`](https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.is_empty-1)
+- [`NonNull::<[T]>::is_empty`](https://doc.rust-lang.org/stable/core/ptr/struct.NonNull.html#method.is_empty)
+- [`CStr::count_bytes`](https://doc.rust-lang.org/stable/core/ffi/c_str/struct.CStr.html#method.count_bytes)
+- [`io::Error::downcast`](https://doc.rust-lang.org/stable/std/io/struct.Error.html#method.downcast)
+- [`num::NonZero<T>`](https://doc.rust-lang.org/stable/core/num/struct.NonZero.html)
+- [`path::absolute`](https://doc.rust-lang.org/stable/std/path/fn.absolute.html)
+- [`proc_macro::Literal::byte_character`](https://doc.rust-lang.org/stable/proc_macro/struct.Literal.html#method.byte_character)
+- [`proc_macro::Literal::c_string`](https://doc.rust-lang.org/stable/proc_macro/struct.Literal.html#method.c_string)
+
+These APIs are now stable in const contexts:
+
+- [`Atomic*::into_inner`](https://doc.rust-lang.org/stable/core/sync/atomic/struct.AtomicUsize.html#method.into_inner)
+- [`io::Cursor::new`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.new)
+- [`io::Cursor::get_ref`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_ref)
+- [`io::Cursor::position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.position)
+- [`io::empty`](https://doc.rust-lang.org/stable/std/io/fn.empty.html)
+- [`io::repeat`](https://doc.rust-lang.org/stable/std/io/fn.repeat.html)
+- [`io::sink`](https://doc.rust-lang.org/stable/std/io/fn.sink.html)
+- [`panic::Location::caller`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.caller)
+- [`panic::Location::file`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.file)
+- [`panic::Location::line`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.line)
+- [`panic::Location::column`](https://doc.rust-lang.org/stable/std/panic/struct.Location.html#method.column)
+
+<a id="1.79.0-Cargo"></a>
+
+Cargo
+-----
+
+- [Prevent dashes in `lib.name`, always normalizing to `_`.](https://github.com/rust-lang/cargo/pull/12783/)
+- [Stabilize MSRV-aware version requirement selection in `cargo add`.](https://github.com/rust-lang/cargo/pull/13608/)
+- [Switch to using `gitoxide` by default for listing files.](https://github.com/rust-lang/cargo/pull/13696/)
+- [Error on `[project]` in Edition 2024; `cargo fix --edition` will change it to `[package]`.](https://github.com/rust-lang/cargo/pull/13747/)
+
+<a id="1.79.0-Rustdoc"></a>
+
+Rustdoc
+-----
+
+- [Always display stability version even if it's the same as the containing item.](https://github.com/rust-lang/rust/pull/118441/)
+- [Show a single search result for items with multiple paths.](https://github.com/rust-lang/rust/pull/119912/)
+- [Support typing `/` in docs to begin a search.](https://github.com/rust-lang/rust/pull/123355/)
+
+<a id="1.79.0-Misc"></a>
+
+Misc
+----
+
+<a id="1.79.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+
+- [Update the minimum external LLVM to 17.](https://github.com/rust-lang/rust/pull/122649/)
+- [`RustcEncodable` and `RustcDecodable` are soft-destabilized, to be removed
+  from the prelude in next edition.](https://github.com/rust-lang/rust/pull/116016/)
+- [The `wasm_c_abi` future-incompatibility lint will warn about use of the
+  non-spec-compliant C ABI.](https://github.com/rust-lang/rust/pull/117918/)
+  Use `wasm-bindgen v0.2.88` to generate forward-compatible bindings.
+- [Check return types of function types for well-formedness](https://github.com/rust-lang/rust/pull/115538)
+
 Version 1.78.0 (2024-05-02)
 ==========================
 
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index ebfb372329e..459d15b1cac 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -83,8 +83,8 @@
 //! that contain `AllocId`s.
 
 use rustc_const_eval::const_eval::DummyMachine;
-use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemoryKind};
-use rustc_const_eval::interpret::{ImmTy, InterpCx, OpTy, Projectable, Scalar};
+use rustc_const_eval::interpret::{intern_const_alloc_for_constprop, MemPlaceMeta, MemoryKind};
+use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable, Scalar};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_hir::def::DefKind;
@@ -99,7 +99,7 @@ use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::DUMMY_SP;
-use rustc_target::abi::{self, Abi, Size, VariantIdx, FIRST_VARIANT};
+use rustc_target::abi::{self, Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
 use smallvec::SmallVec;
 use std::borrow::Cow;
 
@@ -177,6 +177,12 @@ enum AggregateTy<'tcx> {
     Array,
     Tuple,
     Def(DefId, ty::GenericArgsRef<'tcx>),
+    RawPtr {
+        /// Needed for cast propagation.
+        data_pointer_ty: Ty<'tcx>,
+        /// The data pointer can be anything thin, so doesn't determine the output.
+        output_pointer_ty: Ty<'tcx>,
+    },
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
@@ -385,11 +391,22 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     AggregateTy::Def(def_id, args) => {
                         self.tcx.type_of(def_id).instantiate(self.tcx, args)
                     }
+                    AggregateTy::RawPtr { output_pointer_ty, .. } => output_pointer_ty,
                 };
                 let variant = if ty.is_enum() { Some(variant) } else { None };
                 let ty = self.ecx.layout_of(ty).ok()?;
                 if ty.is_zst() {
                     ImmTy::uninit(ty).into()
+                } else if matches!(kind, AggregateTy::RawPtr { .. }) {
+                    // Pointers don't have fields, so don't `project_field` them.
+                    let data = self.ecx.read_pointer(fields[0]).ok()?;
+                    let meta = if fields[1].layout.is_zst() {
+                        MemPlaceMeta::None
+                    } else {
+                        MemPlaceMeta::Meta(self.ecx.read_scalar(fields[1]).ok()?)
+                    };
+                    let ptr_imm = Immediate::new_pointer_with_meta(data, meta, &self.ecx);
+                    ImmTy::from_immediate(ptr_imm, ty).into()
                 } else if matches!(ty.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) {
                     let dest = self.ecx.allocate(ty, MemoryKind::Stack).ok()?;
                     let variant_dest = if let Some(variant) = variant {
@@ -864,10 +881,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         rvalue: &mut Rvalue<'tcx>,
         location: Location,
     ) -> Option<VnIndex> {
-        let Rvalue::Aggregate(box ref kind, ref mut fields) = *rvalue else { bug!() };
+        let Rvalue::Aggregate(box ref kind, ref mut field_ops) = *rvalue else { bug!() };
 
         let tcx = self.tcx;
-        if fields.is_empty() {
+        if field_ops.is_empty() {
             let is_zst = match *kind {
                 AggregateKind::Array(..)
                 | AggregateKind::Tuple
@@ -886,13 +903,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
         }
 
-        let (ty, variant_index) = match *kind {
+        let (mut ty, variant_index) = match *kind {
             AggregateKind::Array(..) => {
-                assert!(!fields.is_empty());
+                assert!(!field_ops.is_empty());
                 (AggregateTy::Array, FIRST_VARIANT)
             }
             AggregateKind::Tuple => {
-                assert!(!fields.is_empty());
+                assert!(!field_ops.is_empty());
                 (AggregateTy::Tuple, FIRST_VARIANT)
             }
             AggregateKind::Closure(did, args)
@@ -903,15 +920,49 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             }
             // Do not track unions.
             AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
-            // FIXME: Do the extra work to GVN `from_raw_parts`
-            AggregateKind::RawPtr(..) => return None,
+            AggregateKind::RawPtr(pointee_ty, mtbl) => {
+                assert_eq!(field_ops.len(), 2);
+                let data_pointer_ty = field_ops[FieldIdx::ZERO].ty(self.local_decls, self.tcx);
+                let output_pointer_ty = Ty::new_ptr(self.tcx, pointee_ty, mtbl);
+                (AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty }, FIRST_VARIANT)
+            }
         };
 
-        let fields: Option<Vec<_>> = fields
+        let fields: Option<Vec<_>> = field_ops
             .iter_mut()
             .map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
             .collect();
-        let fields = fields?;
+        let mut fields = fields?;
+
+        if let AggregateTy::RawPtr { data_pointer_ty, output_pointer_ty } = &mut ty {
+            let mut was_updated = false;
+
+            // Any thin pointer of matching mutability is fine as the data pointer.
+            while let Value::Cast {
+                kind: CastKind::PtrToPtr,
+                value: cast_value,
+                from: cast_from,
+                to: _,
+            } = self.get(fields[0])
+                && let ty::RawPtr(from_pointee_ty, from_mtbl) = cast_from.kind()
+                && let ty::RawPtr(_, output_mtbl) = output_pointer_ty.kind()
+                && from_mtbl == output_mtbl
+                && from_pointee_ty.is_sized(self.tcx, self.param_env)
+            {
+                fields[0] = *cast_value;
+                *data_pointer_ty = *cast_from;
+                was_updated = true;
+            }
+
+            if was_updated {
+                if let Some(const_) = self.try_as_constant(fields[0]) {
+                    field_ops[FieldIdx::ZERO] = Operand::Constant(Box::new(const_));
+                } else if let Some(local) = self.try_as_local(fields[0], location) {
+                    field_ops[FieldIdx::ZERO] = Operand::Copy(Place::from(local));
+                    self.reused_locals.insert(local);
+                }
+            }
+        }
 
         if let AggregateTy::Array = ty
             && fields.len() > 4
@@ -943,6 +994,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             (UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
                 Value::BinaryOp(BinOp::Eq, *lhs, *rhs)
             }
+            (UnOp::PtrMetadata, Value::Aggregate(AggregateTy::RawPtr { .. }, _, fields)) => {
+                return Some(fields[1]);
+            }
             _ => return None,
         };
 
@@ -1094,6 +1148,23 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             return self.new_opaque();
         }
 
+        let mut was_updated = false;
+
+        // If that cast just casts away the metadata again,
+        if let PtrToPtr = kind
+            && let Value::Aggregate(AggregateTy::RawPtr { data_pointer_ty, .. }, _, fields) =
+                self.get(value)
+            && let ty::RawPtr(to_pointee, _) = to.kind()
+            && to_pointee.is_sized(self.tcx, self.param_env)
+        {
+            from = *data_pointer_ty;
+            value = fields[0];
+            was_updated = true;
+            if *data_pointer_ty == to {
+                return Some(fields[0]);
+            }
+        }
+
         if let PtrToPtr | PointerCoercion(MutToConstPointer) = kind
             && let Value::Cast { kind: inner_kind, value: inner_value, from: inner_from, to: _ } =
                 *self.get(value)
@@ -1102,9 +1173,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             from = inner_from;
             value = inner_value;
             *kind = PtrToPtr;
+            was_updated = true;
             if inner_from == to {
                 return Some(inner_value);
             }
+        }
+
+        if was_updated {
             if let Some(const_) = self.try_as_constant(value) {
                 *operand = Operand::Constant(Box::new(const_));
             } else if let Some(local) = self.try_as_local(value, location) {
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 9362dc87654..129f62fb43d 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -68,6 +68,13 @@ pub mod consts {
     pub const FRAC_1_SQRT_PI: f128 =
         0.564189583547756286948079451560772585844050629328998856844086_f128;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "f128", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f128 =
+        0.398942280401432677939946059934381868475858631164934657665926_f128;
+
     /// 2/π
     #[unstable(feature = "f128", issue = "116909")]
     pub const FRAC_2_PI: f128 = 0.636619772367581343075535053490057448137838582961825794990669_f128;
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index c4d4584544b..7a488cd6bf6 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -67,6 +67,12 @@ pub mod consts {
     // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
     pub const FRAC_1_SQRT_PI: f16 = 0.564189583547756286948079451560772586_f16;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "f16", issue = "116909")]
+    // Also, #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f16 = 0.398942280401432677939946059934381868_f16;
+
     /// 2/π
     #[unstable(feature = "f16", issue = "116909")]
     pub const FRAC_2_PI: f16 = 0.636619772367581343075535053490057448_f16;
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 22b24937cbc..9d34d3da9e9 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -327,6 +327,11 @@ pub mod consts {
     #[unstable(feature = "more_float_constants", issue = "103883")]
     pub const FRAC_1_SQRT_PI: f32 = 0.564189583547756286948079451560772586_f32;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f32 = 0.398942280401432677939946059934381868_f32;
+
     /// 2/π
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 34357d1b05a..95f021b2541 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -327,6 +327,11 @@ pub mod consts {
     #[unstable(feature = "more_float_constants", issue = "103883")]
     pub const FRAC_1_SQRT_PI: f64 = 0.564189583547756286948079451560772586_f64;
 
+    /// 1/sqrt(2π)
+    #[doc(alias = "FRAC_1_SQRT_TAU")]
+    #[unstable(feature = "more_float_constants", issue = "103883")]
+    pub const FRAC_1_SQRT_2PI: f64 = 0.398942280401432677939946059934381868_f64;
+
     /// 2/π
     #[stable(feature = "rust1", since = "1.0.0")]
     pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64;
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 91039d0c8dc..60b1ff3e441 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1041,6 +1041,21 @@ impl Step for PlainSourceTarball {
                 .env("RUSTC_BOOTSTRAP", "1")
                 .current_dir(plain_dst_src);
 
+            // Vendor packages that are required by opt-dist to collect PGO profiles.
+            let pkgs_for_pgo_training = build_helper::LLVM_PGO_CRATES
+                .iter()
+                .chain(build_helper::RUSTC_PGO_CRATES)
+                .map(|pkg| {
+                    let mut manifest_path =
+                        builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks");
+                    manifest_path.push(pkg);
+                    manifest_path.push("Cargo.toml");
+                    manifest_path
+                });
+            for manifest_path in pkgs_for_pgo_training {
+                cmd.arg("--sync").arg(manifest_path);
+            }
+
             let config = if !builder.config.dry_run() {
                 t!(String::from_utf8(t!(cmd.output()).stdout))
             } else {
diff --git a/src/tools/build_helper/README.md b/src/tools/build_helper/README.md
new file mode 100644
index 00000000000..f81b631c3fd
--- /dev/null
+++ b/src/tools/build_helper/README.md
@@ -0,0 +1 @@
+Types and functions shared across tools in this workspace.
diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs
index 2abda5d3ebf..15807d1c0d8 100644
--- a/src/tools/build_helper/src/lib.rs
+++ b/src/tools/build_helper/src/lib.rs
@@ -1,5 +1,30 @@
+//! Types and functions shared across tools in this workspace.
+
 pub mod ci;
 pub mod git;
 pub mod metrics;
 pub mod stage0_parser;
 pub mod util;
+
+/// The default set of crates for opt-dist to collect LLVM profiles.
+pub const LLVM_PGO_CRATES: &[&str] = &[
+    "syn-1.0.89",
+    "cargo-0.60.0",
+    "serde-1.0.136",
+    "ripgrep-13.0.0",
+    "regex-1.5.5",
+    "clap-3.1.6",
+    "hyper-0.14.18",
+];
+
+/// The default set of crates for opt-dist to collect rustc profiles.
+pub const RUSTC_PGO_CRATES: &[&str] = &[
+    "externs",
+    "ctfe-stress-5",
+    "cargo-0.60.0",
+    "token-stream-stress",
+    "match-stress",
+    "tuple-stress",
+    "diesel-1.4.8",
+    "bitmaps-3.1.0",
+];
diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs
index 09263dc645e..89f4d8957c8 100644
--- a/src/tools/opt-dist/src/training.rs
+++ b/src/tools/opt-dist/src/training.rs
@@ -3,30 +3,10 @@ use crate::exec::{cmd, CmdBuilder};
 use crate::utils::io::{count_files, delete_directory};
 use crate::utils::with_log_group;
 use anyhow::Context;
+use build_helper::{LLVM_PGO_CRATES, RUSTC_PGO_CRATES};
 use camino::{Utf8Path, Utf8PathBuf};
 use humansize::BINARY;
 
-const LLVM_PGO_CRATES: &[&str] = &[
-    "syn-1.0.89",
-    "cargo-0.60.0",
-    "serde-1.0.136",
-    "ripgrep-13.0.0",
-    "regex-1.5.5",
-    "clap-3.1.6",
-    "hyper-0.14.18",
-];
-
-const RUSTC_PGO_CRATES: &[&str] = &[
-    "externs",
-    "ctfe-stress-5",
-    "cargo-0.60.0",
-    "token-stream-stress",
-    "match-stress",
-    "tuple-stress",
-    "diesel-1.4.8",
-    "bitmaps-3.1.0",
-];
-
 fn init_compiler_benchmarks(
     env: &Environment,
     profiles: &[&str],
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index b17f217c133..cea1313e29d 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -318,38 +318,30 @@ pub fn run_in_tmpdir<F: FnOnce()>(callback: F) {
 }
 
 /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
-/// containing a `cmd: Command` field and a `output` function. The provided helpers are:
+/// containing a `cmd: Command` field. The provided helpers are:
 ///
 /// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
 ///    to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
 ///    new specific helper methods over relying on these generic argument providers.
 /// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
 ///    methods of the same name on [`Command`].
-/// 3. Output and execution: `output`, `run` and `run_fail` are provided. `output` waits for the
-///    command to finish running and returns the process's [`Output`]. `run` and `run_fail` are
-///    higher-level convenience methods which waits for the command to finish running and assert
-///    that the command successfully ran or failed as expected. Prefer `run` and `run_fail` when
-///    possible.
+/// 3. Output and execution: `run` and `run_fail` are provided. These are
+///    higher-level convenience methods which wait for the command to finish running and assert
+///    that the command successfully ran or failed as expected. They return
+///    [`CompletedProcess`], which can be used to assert the stdout/stderr/exit code of the executed
+///    process.
 ///
 /// Example usage:
 ///
 /// ```ignore (illustrative)
 /// struct CommandWrapper { cmd: Command } // <- required `cmd` field
 ///
-/// impl CommandWrapper {
-///     /// Get the [`Output`][::std::process::Output] of the finished process.
-///     pub fn command_output(&mut self) -> Output { /* ... */ } // <- required `command_output()` method
-/// }
-///
 /// crate::impl_common_helpers!(CommandWrapper);
 ///
 /// impl CommandWrapper {
 ///     // ... additional specific helper methods
 /// }
 /// ```
-///
-/// [`Command`]: ::std::process::Command
-/// [`Output`]: ::std::process::Output
 macro_rules! impl_common_helpers {
     ($wrapper: ident) => {
         impl $wrapper {
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index efcd2a181ff..7b93b09dda2 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -67,6 +67,7 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>)
     //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
     //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
     ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None),
+    ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None),
     ("src/tools/x", &[], None),
     // tidy-alphabetical-end
 ];
@@ -142,6 +143,22 @@ const EXCEPTIONS_RUST_ANALYZER: ExceptionList = &[
     // tidy-alphabetical-end
 ];
 
+const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[
+    // tidy-alphabetical-start
+    ("alloc-no-stdlib", "BSD-3-Clause"),
+    ("alloc-stdlib", "BSD-3-Clause"),
+    ("brotli", "BSD-3-Clause/MIT"),
+    ("brotli-decompressor", "BSD-3-Clause/MIT"),
+    ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"),
+    ("inferno", "CDDL-1.0"),
+    ("instant", "BSD-3-Clause"),
+    ("ring", NON_STANDARD_LICENSE), // see EXCEPTIONS_NON_STANDARD_LICENSE_DEPS for more.
+    ("ryu", "Apache-2.0 OR BSL-1.0"),
+    ("snap", "BSD-3-Clause"),
+    ("subtle", "BSD-3-Clause"),
+    // tidy-alphabetical-end
+];
+
 const EXCEPTIONS_CRANELIFT: ExceptionList = &[
     // tidy-alphabetical-start
     ("cranelift-bforest", "Apache-2.0 WITH LLVM-exception"),
@@ -178,6 +195,20 @@ const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[
     ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptible, but we use it under MIT OR Apache-2.0
 ];
 
+/// Placeholder for non-standard license file.
+const NON_STANDARD_LICENSE: &str = "NON_STANDARD_LICENSE";
+
+/// These dependencies have non-standard licenses but are genenrally permitted.
+const EXCEPTIONS_NON_STANDARD_LICENSE_DEPS: &[&str] = &[
+    // `ring` is included because it is an optional dependency of `hyper`,
+    // which is a training data in rustc-perf for optimized build.
+    // The license of it is generally `ISC AND MIT AND OpenSSL`,
+    // though the `package.license` field is not set.
+    //
+    // See https://github.com/briansmith/ring/issues/902
+    "ring",
+];
+
 /// These are the root crates that are part of the runtime. The licenses for
 /// these and all their dependencies *must not* be in the exception list.
 const RUNTIME_CRATES: &[&str] = &["std", "core", "alloc", "test", "panic_abort", "panic_unwind"];
@@ -610,6 +641,11 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba
         for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
             match &pkg.license {
                 None => {
+                    if *license == NON_STANDARD_LICENSE
+                        && EXCEPTIONS_NON_STANDARD_LICENSE_DEPS.contains(&pkg.name.as_str())
+                    {
+                        continue;
+                    }
                     tidy_error!(
                         bad,
                         "dependency exception `{}` does not declare a license expression",
diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs
index ff71ca53725..2118de5f204 100644
--- a/src/tools/tidy/src/extdeps.rs
+++ b/src/tools/tidy/src/extdeps.rs
@@ -4,7 +4,11 @@ use std::fs;
 use std::path::Path;
 
 /// List of allowed sources for packages.
-const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crates.io-index\""];
+const ALLOWED_SOURCES: &[&str] = &[
+    r#""registry+https://github.com/rust-lang/crates.io-index""#,
+    // This is `rust_team_data` used by `site` in src/tools/rustc-perf,
+    r#""git+https://github.com/rust-lang/team#a5260e76d3aa894c64c56e6ddc8545b9a98043ec""#,
+];
 
 /// Checks for external package sources. `root` is the path to the directory that contains the
 /// workspace `Cargo.toml`.
diff --git a/tests/assembly/asm/global_asm.rs b/tests/assembly/asm/global_asm.rs
index 8f824563e8a..22cf4bdb15b 100644
--- a/tests/assembly/asm/global_asm.rs
+++ b/tests/assembly/asm/global_asm.rs
@@ -25,9 +25,9 @@ global_asm!("movl ${}, %ecx", const 5, options(att_syntax));
 global_asm!("call {}", sym my_func);
 // CHECK: lea rax, [rip + MY_STATIC]
 global_asm!("lea rax, [rip + {}]", sym MY_STATIC);
-// CHECK: call _RNvCsddMtV7nAi4C_10global_asm6foobar
+// CHECK: call _RNvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_10global_asm6foobar
 global_asm!("call {}", sym foobar);
-// CHECK: _RNvCsddMtV7nAi4C_10global_asm6foobar:
+// CHECK: _RNvC[[CRATE_IDENT]]_10global_asm6foobar:
 fn foobar() {
     loop {}
 }
diff --git a/tests/codegen/consts.rs b/tests/codegen/consts.rs
index 93c58c37c28..42ce7679d1a 100644
--- a/tests/codegen/consts.rs
+++ b/tests/codegen/consts.rs
@@ -9,11 +9,11 @@
 // CHECK: @STATIC = {{.*}}, align 4
 
 // This checks the constants from inline_enum_const
-// CHECK: @alloc_af1f8e8e6f4b341431a1d405e652df2d = {{.*}}, align 2
+// CHECK: @alloc_[[INLINE_ENUM_HASH:[a-f0-9]{32}]] = {{.*}}, align 2
 
 // This checks the constants from {low,high}_align_const, they share the same
 // constant, but the alignment differs, so the higher one should be used
-// CHECK: [[LOW_HIGH:@alloc_[a-f0-9]+]] = {{.*}}, align 4
+// CHECK: [[LOW_HIGH:@alloc_[a-f0-9]{32}]] = {{.*}}, align 4
 
 #[derive(Copy, Clone)]
 // repr(i16) is required for the {low,high}_align_const test
diff --git a/tests/codegen/pattern_type_symbols.rs b/tests/codegen/pattern_type_symbols.rs
index dfe83443348..a99b3efca41 100644
--- a/tests/codegen/pattern_type_symbols.rs
+++ b/tests/codegen/pattern_type_symbols.rs
@@ -15,9 +15,9 @@ fn foo<T>() {}
 
 pub fn bar() {
     // CHECK: call pattern_type_symbols::foo::<u32>
-    // CHECK: call void @_RINvCs3QvG2ESzx2Q_20pattern_type_symbols3foomEB2_
+    // CHECK: call void @_RINvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_20pattern_type_symbols3foomEB2_
     foo::<u32>();
     // CHECK: call pattern_type_symbols::foo::<(u32, [(); 0], [(); 999999999], [(); true])>
-    // CHECK: call void @_RINvCs3QvG2ESzx2Q_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_Aub1_EEB2_
+    // CHECK: call void @_RINvC[[CRATE_IDENT]]_20pattern_type_symbols3fooTmAum0_Aum3b9ac9ff_Aub1_EEB2_
     foo::<NanoU32>();
 }
diff --git a/tests/codegen/virtual-function-elimination.rs b/tests/codegen/virtual-function-elimination.rs
index 6c391d9114b..23d7657baa9 100644
--- a/tests/codegen/virtual-function-elimination.rs
+++ b/tests/codegen/virtual-function-elimination.rs
@@ -81,7 +81,7 @@ fn taking_u(u: &dyn U) -> i32 {
 }
 
 pub fn taking_v(v: &dyn V) -> i32 {
-    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtCs64ITQYi9761_28virtual_function_elimination1V")
+    // CHECK: @llvm.type.checked.load({{.*}}, i32 24, metadata !"NtC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_28virtual_function_elimination1V")
     v.public_function()
 }
 
@@ -96,5 +96,5 @@ pub fn main() {
 // CHECK: ![[TYPE0]] = !{i64 0, !"[[MANGLED_TYPE0]]"}
 // CHECK: ![[VCALL_VIS0]] = !{i64 2}
 // CHECK: ![[TYPE1]] = !{i64 0, !"[[MANGLED_TYPE1]]"}
-// CHECK: ![[TYPE2]] = !{i64 0, !"NtCs64ITQYi9761_28virtual_function_elimination1V"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"NtC[[CRATE_IDENT]]_28virtual_function_elimination1V"}
 // CHECK: ![[VCALL_VIS2]] = !{i64 1}
diff --git a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff
new file mode 100644
index 00000000000..6e5bdb16595
--- /dev/null
+++ b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-abort.diff
@@ -0,0 +1,60 @@
+- // MIR for `casts_before_aggregate_raw_ptr` before GVN
++ // MIR for `casts_before_aggregate_raw_ptr` after GVN
+  
+  fn casts_before_aggregate_raw_ptr(_1: *const u32) -> *const [u8] {
+      debug x => _1;
+      let mut _0: *const [u8];
+      let _2: *const [u8; 4];
+      let mut _3: *const u32;
+      let mut _5: *const [u8; 4];
+      let mut _7: *const u8;
+      let mut _8: *const ();
+      scope 1 {
+          debug x => _2;
+          let _4: *const u8;
+          scope 2 {
+              debug x => _4;
+              let _6: *const ();
+              scope 3 {
+                  debug x => _6;
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = move _3 as *const [u8; 4] (PtrToPtr);
++         _2 = _1 as *const [u8; 4] (PtrToPtr);
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          StorageLive(_5);
+          _5 = _2;
+-         _4 = move _5 as *const u8 (PtrToPtr);
++         _4 = _1 as *const u8 (PtrToPtr);
+          StorageDead(_5);
+-         StorageLive(_6);
++         nop;
+          StorageLive(_7);
+          _7 = _4;
+-         _6 = move _7 as *const () (PtrToPtr);
++         _6 = _1 as *const () (PtrToPtr);
+          StorageDead(_7);
+          StorageLive(_8);
+          _8 = _6;
+-         _0 = *const [u8] from (move _8, const 4_usize);
++         _0 = *const [u8] from (_1, const 4_usize);
+          StorageDead(_8);
+-         StorageDead(_6);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..6e5bdb16595
--- /dev/null
+++ b/tests/mir-opt/gvn.casts_before_aggregate_raw_ptr.GVN.panic-unwind.diff
@@ -0,0 +1,60 @@
+- // MIR for `casts_before_aggregate_raw_ptr` before GVN
++ // MIR for `casts_before_aggregate_raw_ptr` after GVN
+  
+  fn casts_before_aggregate_raw_ptr(_1: *const u32) -> *const [u8] {
+      debug x => _1;
+      let mut _0: *const [u8];
+      let _2: *const [u8; 4];
+      let mut _3: *const u32;
+      let mut _5: *const [u8; 4];
+      let mut _7: *const u8;
+      let mut _8: *const ();
+      scope 1 {
+          debug x => _2;
+          let _4: *const u8;
+          scope 2 {
+              debug x => _4;
+              let _6: *const ();
+              scope 3 {
+                  debug x => _6;
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = move _3 as *const [u8; 4] (PtrToPtr);
++         _2 = _1 as *const [u8; 4] (PtrToPtr);
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          StorageLive(_5);
+          _5 = _2;
+-         _4 = move _5 as *const u8 (PtrToPtr);
++         _4 = _1 as *const u8 (PtrToPtr);
+          StorageDead(_5);
+-         StorageLive(_6);
++         nop;
+          StorageLive(_7);
+          _7 = _4;
+-         _6 = move _7 as *const () (PtrToPtr);
++         _6 = _1 as *const () (PtrToPtr);
+          StorageDead(_7);
+          StorageLive(_8);
+          _8 = _6;
+-         _0 = *const [u8] from (move _8, const 4_usize);
++         _0 = *const [u8] from (_1, const 4_usize);
+          StorageDead(_8);
+-         StorageDead(_6);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff
new file mode 100644
index 00000000000..73dbabb56b3
--- /dev/null
+++ b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-abort.diff
@@ -0,0 +1,32 @@
+- // MIR for `meta_of_ref_to_slice` before GVN
++ // MIR for `meta_of_ref_to_slice` after GVN
+  
+  fn meta_of_ref_to_slice(_1: *const i32) -> usize {
+      debug x => _1;
+      let mut _0: usize;
+      let _2: *const [i32];
+      let mut _3: *const i32;
+      let mut _4: *const [i32];
+      scope 1 {
+          debug ptr => _2;
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = *const [i32] from (move _3, const 1_usize);
++         _2 = *const [i32] from (_1, const 1_usize);
+          StorageDead(_3);
+          StorageLive(_4);
+          _4 = _2;
+-         _0 = PtrMetadata(move _4);
++         _0 = const 1_usize;
+          StorageDead(_4);
+-         StorageDead(_2);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..73dbabb56b3
--- /dev/null
+++ b/tests/mir-opt/gvn.meta_of_ref_to_slice.GVN.panic-unwind.diff
@@ -0,0 +1,32 @@
+- // MIR for `meta_of_ref_to_slice` before GVN
++ // MIR for `meta_of_ref_to_slice` after GVN
+  
+  fn meta_of_ref_to_slice(_1: *const i32) -> usize {
+      debug x => _1;
+      let mut _0: usize;
+      let _2: *const [i32];
+      let mut _3: *const i32;
+      let mut _4: *const [i32];
+      scope 1 {
+          debug ptr => _2;
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = _1;
+-         _2 = *const [i32] from (move _3, const 1_usize);
++         _2 = *const [i32] from (_1, const 1_usize);
+          StorageDead(_3);
+          StorageLive(_4);
+          _4 = _2;
+-         _0 = PtrMetadata(move _4);
++         _0 = const 1_usize;
+          StorageDead(_4);
+-         StorageDead(_2);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs
index 315377e4356..720018f112e 100644
--- a/tests/mir-opt/gvn.rs
+++ b/tests/mir-opt/gvn.rs
@@ -783,6 +783,39 @@ fn non_freeze<T: Copy>(x: T) {
     }
 }
 
+// Check that we can const-prop into `from_raw_parts`
+fn slice_const_length(x: &[i32]) -> *const [i32] {
+    // CHECK-LABEL: fn slice_const_length(
+    // CHECK: _0 = *const [i32] from ({{_[0-9]+}}, const 123_usize);
+    let ptr = x.as_ptr();
+    let len = 123;
+    std::intrinsics::aggregate_raw_ptr(ptr, len)
+}
+
+fn meta_of_ref_to_slice(x: *const i32) -> usize {
+    // CHECK-LABEL: fn meta_of_ref_to_slice
+    // CHECK: _0 = const 1_usize
+    let ptr: *const [i32] = std::intrinsics::aggregate_raw_ptr(x, 1);
+    std::intrinsics::ptr_metadata(ptr)
+}
+
+fn slice_from_raw_parts_as_ptr(x: *const u16, n: usize) -> (*const u16, *const f32) {
+    // CHECK-LABEL: fn slice_from_raw_parts_as_ptr
+    // CHECK: _8 = _1 as *const f32 (PtrToPtr);
+    // CHECK: _0 = (_1, move _8);
+    let ptr: *const [u16] = std::intrinsics::aggregate_raw_ptr(x, n);
+    (ptr as *const u16, ptr as *const f32)
+}
+
+fn casts_before_aggregate_raw_ptr(x: *const u32) -> *const [u8] {
+    // CHECK-LABEL: fn casts_before_aggregate_raw_ptr
+    // CHECK: _0 = *const [u8] from (_1, const 4_usize);
+    let x = x as *const [u8; 4];
+    let x = x as *const u8;
+    let x = x as *const ();
+    std::intrinsics::aggregate_raw_ptr(x, 4)
+}
+
 fn main() {
     subexpression_elimination(2, 4, 5);
     wrap_unwrap(5);
@@ -807,6 +840,9 @@ fn main() {
     wide_ptr_integer();
     borrowed(5);
     non_freeze(5);
+    slice_const_length(&[1]);
+    meta_of_ref_to_slice(&42);
+    slice_from_raw_parts_as_ptr(&123, 456);
 }
 
 #[inline(never)]
@@ -840,3 +876,7 @@ fn identity<T>(x: T) -> T {
 // EMIT_MIR gvn.wide_ptr_integer.GVN.diff
 // EMIT_MIR gvn.borrowed.GVN.diff
 // EMIT_MIR gvn.non_freeze.GVN.diff
+// EMIT_MIR gvn.slice_const_length.GVN.diff
+// EMIT_MIR gvn.meta_of_ref_to_slice.GVN.diff
+// EMIT_MIR gvn.slice_from_raw_parts_as_ptr.GVN.diff
+// EMIT_MIR gvn.casts_before_aggregate_raw_ptr.GVN.diff
diff --git a/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff b/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff
new file mode 100644
index 00000000000..fd5fa035d81
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_const_length.GVN.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `slice_const_length` before GVN
++ // MIR for `slice_const_length` after GVN
+  
+  fn slice_const_length(_1: &[i32]) -> *const [i32] {
+      debug x => _1;
+      let mut _0: *const [i32];
+      let _2: *const i32;
+      let mut _3: &[i32];
+      let mut _5: *const i32;
+      let mut _6: usize;
+      scope 1 {
+          debug ptr => _2;
+          let _4: usize;
+          scope 2 {
+              debug len => _4;
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = &(*_1);
+          _2 = core::slice::<impl [i32]>::as_ptr(move _3) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          _4 = const 123_usize;
+          StorageLive(_5);
+          _5 = _2;
+          StorageLive(_6);
+-         _6 = _4;
+-         _0 = *const [i32] from (move _5, move _6);
++         _6 = const 123_usize;
++         _0 = *const [i32] from (_2, const 123_usize);
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..98945cf9724
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_const_length.GVN.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `slice_const_length` before GVN
++ // MIR for `slice_const_length` after GVN
+  
+  fn slice_const_length(_1: &[i32]) -> *const [i32] {
+      debug x => _1;
+      let mut _0: *const [i32];
+      let _2: *const i32;
+      let mut _3: &[i32];
+      let mut _5: *const i32;
+      let mut _6: usize;
+      scope 1 {
+          debug ptr => _2;
+          let _4: usize;
+          scope 2 {
+              debug len => _4;
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_2);
++         nop;
+          StorageLive(_3);
+          _3 = &(*_1);
+          _2 = core::slice::<impl [i32]>::as_ptr(move _3) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          StorageDead(_3);
+-         StorageLive(_4);
++         nop;
+          _4 = const 123_usize;
+          StorageLive(_5);
+          _5 = _2;
+          StorageLive(_6);
+-         _6 = _4;
+-         _0 = *const [i32] from (move _5, move _6);
++         _6 = const 123_usize;
++         _0 = *const [i32] from (_2, const 123_usize);
+          StorageDead(_6);
+          StorageDead(_5);
+-         StorageDead(_4);
+-         StorageDead(_2);
++         nop;
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff
new file mode 100644
index 00000000000..75bcd2a8d72
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-abort.diff
@@ -0,0 +1,51 @@
+- // MIR for `slice_from_raw_parts_as_ptr` before GVN
++ // MIR for `slice_from_raw_parts_as_ptr` after GVN
+  
+  fn slice_from_raw_parts_as_ptr(_1: *const u16, _2: usize) -> (*const u16, *const f32) {
+      debug x => _1;
+      debug n => _2;
+      let mut _0: (*const u16, *const f32);
+      let _3: *const [u16];
+      let mut _4: *const u16;
+      let mut _5: usize;
+      let mut _6: *const u16;
+      let mut _7: *const [u16];
+      let mut _8: *const f32;
+      let mut _9: *const [u16];
+      scope 1 {
+          debug ptr => _3;
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = _1;
+          StorageLive(_5);
+          _5 = _2;
+-         _3 = *const [u16] from (move _4, move _5);
++         _3 = *const [u16] from (_1, _2);
+          StorageDead(_5);
+          StorageDead(_4);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = _3;
+-         _6 = move _7 as *const u16 (PtrToPtr);
++         _6 = _1;
+          StorageDead(_7);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = _3;
+-         _8 = move _9 as *const f32 (PtrToPtr);
++         _8 = _1 as *const f32 (PtrToPtr);
+          StorageDead(_9);
+-         _0 = (move _6, move _8);
++         _0 = (_1, move _8);
+          StorageDead(_8);
+          StorageDead(_6);
+-         StorageDead(_3);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..75bcd2a8d72
--- /dev/null
+++ b/tests/mir-opt/gvn.slice_from_raw_parts_as_ptr.GVN.panic-unwind.diff
@@ -0,0 +1,51 @@
+- // MIR for `slice_from_raw_parts_as_ptr` before GVN
++ // MIR for `slice_from_raw_parts_as_ptr` after GVN
+  
+  fn slice_from_raw_parts_as_ptr(_1: *const u16, _2: usize) -> (*const u16, *const f32) {
+      debug x => _1;
+      debug n => _2;
+      let mut _0: (*const u16, *const f32);
+      let _3: *const [u16];
+      let mut _4: *const u16;
+      let mut _5: usize;
+      let mut _6: *const u16;
+      let mut _7: *const [u16];
+      let mut _8: *const f32;
+      let mut _9: *const [u16];
+      scope 1 {
+          debug ptr => _3;
+      }
+  
+      bb0: {
+-         StorageLive(_3);
++         nop;
+          StorageLive(_4);
+          _4 = _1;
+          StorageLive(_5);
+          _5 = _2;
+-         _3 = *const [u16] from (move _4, move _5);
++         _3 = *const [u16] from (_1, _2);
+          StorageDead(_5);
+          StorageDead(_4);
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = _3;
+-         _6 = move _7 as *const u16 (PtrToPtr);
++         _6 = _1;
+          StorageDead(_7);
+          StorageLive(_8);
+          StorageLive(_9);
+          _9 = _3;
+-         _8 = move _9 as *const f32 (PtrToPtr);
++         _8 = _1 as *const f32 (PtrToPtr);
+          StorageDead(_9);
+-         _0 = (move _6, move _8);
++         _0 = (_1, move _8);
+          StorageDead(_8);
+          StorageDead(_6);
+-         StorageDead(_3);
++         nop;
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
index 2c6d93e10c1..2f6139712ff 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-abort.mir
@@ -12,8 +12,7 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
-            let mut _5: *const ();
-            let mut _6: usize;
+            let mut _5: usize;
             scope 5 (inlined std::ptr::metadata::<[u32]>) {
             }
             scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
@@ -28,11 +27,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         _4 = Offset(_3, _2);
         StorageDead(_3);
         StorageLive(_5);
-        _5 = _4 as *const () (PtrToPtr);
-        StorageLive(_6);
-        _6 = PtrMetadata(_1);
-        _0 = *const [u32] from (_5, _6);
-        StorageDead(_6);
+        _5 = PtrMetadata(_1);
+        _0 = *const [u32] from (_4, _5);
         StorageDead(_5);
         StorageDead(_4);
         return;
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
index 2c6d93e10c1..2f6139712ff 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_fat.PreCodegen.after.panic-unwind.mir
@@ -12,8 +12,7 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         scope 3 (inlined std::ptr::const_ptr::<impl *const u8>::add) {
         }
         scope 4 (inlined std::ptr::const_ptr::<impl *const u8>::with_metadata_of::<[u32]>) {
-            let mut _5: *const ();
-            let mut _6: usize;
+            let mut _5: usize;
             scope 5 (inlined std::ptr::metadata::<[u32]>) {
             }
             scope 6 (inlined std::ptr::from_raw_parts::<[u32], ()>) {
@@ -28,11 +27,8 @@ fn demo_byte_add_fat(_1: *const [u32], _2: usize) -> *const [u32] {
         _4 = Offset(_3, _2);
         StorageDead(_3);
         StorageLive(_5);
-        _5 = _4 as *const () (PtrToPtr);
-        StorageLive(_6);
-        _6 = PtrMetadata(_1);
-        _0 = *const [u32] from (_5, _6);
-        StorageDead(_6);
+        _5 = PtrMetadata(_1);
+        _0 = *const [u32] from (_4, _5);
         StorageDead(_5);
         StorageDead(_4);
         return;
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
index 04fb6b838f0..8d47e63eff2 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-abort.mir
@@ -20,11 +20,13 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
     }
 
     bb0: {
+        StorageLive(_4);
         StorageLive(_3);
         _3 = _1 as *const u8 (PtrToPtr);
         _4 = Offset(_3, _2);
         StorageDead(_3);
         _0 = _4 as *const u32 (PtrToPtr);
+        StorageDead(_4);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
index 04fb6b838f0..8d47e63eff2 100644
--- a/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/ptr_offset.demo_byte_add_thin.PreCodegen.after.panic-unwind.mir
@@ -20,11 +20,13 @@ fn demo_byte_add_thin(_1: *const u32, _2: usize) -> *const u32 {
     }
 
     bb0: {
+        StorageLive(_4);
         StorageLive(_3);
         _3 = _1 as *const u8 (PtrToPtr);
         _4 = Offset(_3, _2);
         StorageDead(_3);
         _0 = _4 as *const u32 (PtrToPtr);
+        StorageDead(_4);
         return;
     }
 }