about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_mir_transform/src')
-rw-r--r--compiler/rustc_mir_transform/src/add_call_guards.rs2
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs4
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs6
-rw-r--r--compiler/rustc_mir_transform/src/check_packed_ref.rs7
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs32
-rw-r--r--compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs1
-rw-r--r--compiler/rustc_mir_transform/src/const_debuginfo.rs8
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs94
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs4
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs11
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs129
-rw-r--r--compiler/rustc_mir_transform/src/dead_store_elimination.rs5
-rw-r--r--compiler/rustc_mir_transform/src/deref_separator.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs11
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs2
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs21
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs48
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs15
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs36
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs7
-rw-r--r--compiler/rustc_mir_transform/src/instcombine.rs21
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs201
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs42
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs2
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs2
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs2
-rw-r--r--compiler/rustc_mir_transform/src/remove_place_mention.rs23
-rw-r--r--compiler/rustc_mir_transform/src/reveal_all.rs14
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs3
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs8
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs64
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs23
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs2
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs4
-rw-r--r--compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs4
43 files changed, 411 insertions, 468 deletions
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index e1e354efa1c..fb4705e0754 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -1,5 +1,5 @@
 use crate::MirPass;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index 896fcd9cdd6..b29ffcc70f9 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::patch::MirPatch;
 /// they are dropped from an aligned address.
 ///
 /// For example, if we have something like
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
 /// #[repr(packed)]
 /// struct Foo {
 ///     dealign: u8,
@@ -25,7 +25,7 @@ use rustc_middle::mir::patch::MirPatch;
 /// its address is not aligned.
 ///
 /// Instead, we move `foo.data` to a local and drop that:
-/// ```ignore (ilustrative)
+/// ```ignore (illustrative)
 ///     storage.live(drop_temp)
 ///     drop_temp = foo.data;
 ///     drop(drop_temp) -> next
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 916f2904dda..187d38b385b 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         let basic_blocks = body.basic_blocks.as_mut();
         let local_decls = &body.local_decls;
         let needs_retag = |place: &Place<'tcx>| {
-            !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
+            !place.has_deref() // we're not really interested in stores to "outside" locations, they are hard to keep track of anyway
                 && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
                 && !local_decls[place.local].is_deref_temp()
         };
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index c76dc56065c..d60184e0ebe 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -1,7 +1,7 @@
 use crate::MirPass;
 use rustc_hir::def_id::DefId;
 use rustc_hir::lang_items::LangItem;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
 use rustc_middle::mir::*;
 use rustc_middle::mir::{
     interpret::{ConstValue, Scalar},
@@ -224,10 +224,10 @@ fn insert_alignment_check<'tcx>(
             cond: Operand::Copy(is_ok),
             expected: true,
             target: new_block,
-            msg: AssertKind::MisalignedPointerDereference {
+            msg: Box::new(AssertKind::MisalignedPointerDereference {
                 required: Operand::Copy(alignment),
                 found: Operand::Copy(addr),
-            },
+            }),
             unwind: UnwindAction::Terminate,
         },
     });
diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs
index f5f1c1010e1..b9bc89fcf8f 100644
--- a/compiler/rustc_mir_transform/src/check_packed_ref.rs
+++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs
@@ -56,8 +56,11 @@ impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
                         "reference to packed field is unaligned"
                     )
                     .note(
-                        "fields of packed structs are not properly aligned, and creating \
-                        a misaligned reference is undefined behavior (even if that \
+                        "packed structs are only aligned by one byte, and many modern architectures \
+                        penalize unaligned field accesses"
+                    )
+                    .note(
+                        "creating a misaligned reference is undefined behavior (even if that \
                         reference is never dereferenced)",
                     ).help(
                         "copy the field contents to a local variable, or replace the \
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index d908f6b3a9b..ce6d865a7dc 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -148,7 +148,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
 
             if let Some(uv) = maybe_uneval {
                 if uv.promoted.is_none() {
-                    let def_id = uv.def.def_id_for_type_of();
+                    let def_id = uv.def;
                     if self.tcx.def_kind(def_id) == DefKind::InlineConst {
                         let local_def_id = def_id.expect_local();
                         let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
@@ -375,22 +375,7 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
-    *providers = Providers {
-        unsafety_check_result: |tcx, def_id| {
-            if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
-                tcx.unsafety_check_result_for_const_arg(def)
-            } else {
-                unsafety_check_result(tcx, ty::WithOptConstParam::unknown(def_id))
-            }
-        },
-        unsafety_check_result_for_const_arg: |tcx, (did, param_did)| {
-            unsafety_check_result(
-                tcx,
-                ty::WithOptConstParam { did, const_param_did: Some(param_did) },
-            )
-        },
-        ..*providers
-    };
+    *providers = Providers { unsafety_check_result, ..*providers };
 }
 
 /// Context information for [`UnusedUnsafeVisitor`] traversal,
@@ -492,10 +477,7 @@ fn check_unused_unsafe(
     unused_unsafes
 }
 
-fn unsafety_check_result(
-    tcx: TyCtxt<'_>,
-    def: ty::WithOptConstParam<LocalDefId>,
-) -> &UnsafetyCheckResult {
+fn unsafety_check_result(tcx: TyCtxt<'_>, def: LocalDefId) -> &UnsafetyCheckResult {
     debug!("unsafety_violations({:?})", def);
 
     // N.B., this borrow is valid because all the consumers of
@@ -510,13 +492,13 @@ fn unsafety_check_result(
         });
     }
 
-    let param_env = tcx.param_env(def.did);
+    let param_env = tcx.param_env(def);
 
-    let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
+    let mut checker = UnsafetyChecker::new(body, def, tcx, param_env);
     checker.visit_body(&body);
 
-    let unused_unsafes = (!tcx.is_typeck_child(def.did.to_def_id()))
-        .then(|| check_unused_unsafe(tcx, def.did, &checker.used_unsafe_blocks));
+    let unused_unsafes = (!tcx.is_typeck_child(def.to_def_id()))
+        .then(|| check_unused_unsafe(tcx, def, &checker.used_unsafe_blocks));
 
     tcx.arena.alloc(UnsafetyCheckResult {
         violations: checker.violations,
diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
index 0923824db48..d435d3ee69b 100644
--- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
+++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs
@@ -24,7 +24,6 @@ impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck {
             for statement in basic_block.statements.iter_mut() {
                 match statement.kind {
                     StatementKind::AscribeUserType(..)
-                    | StatementKind::PlaceMention(..)
                     | StatementKind::Assign(box (_, Rvalue::Ref(_, BorrowKind::Shallow, _)))
                     | StatementKind::FakeRead(..) => statement.make_nop(),
                     _ => (),
diff --git a/compiler/rustc_mir_transform/src/const_debuginfo.rs b/compiler/rustc_mir_transform/src/const_debuginfo.rs
index 6f0ae4f07ab..f662ce645b0 100644
--- a/compiler/rustc_mir_transform/src/const_debuginfo.rs
+++ b/compiler/rustc_mir_transform/src/const_debuginfo.rs
@@ -10,19 +10,19 @@ use rustc_middle::{
 };
 
 use crate::MirPass;
-use rustc_index::{bit_set::BitSet, vec::IndexVec};
+use rustc_index::{bit_set::BitSet, IndexVec};
 
 pub struct ConstDebugInfo;
 
 impl<'tcx> MirPass<'tcx> for ConstDebugInfo {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.opts.unstable_opts.unsound_mir_opts && sess.mir_opt_level() > 0
+        sess.mir_opt_level() > 0
     }
 
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         trace!("running ConstDebugInfo on {:?}", body.source);
 
-        for (local, constant) in find_optimization_oportunities(body) {
+        for (local, constant) in find_optimization_opportunities(body) {
             for debuginfo in &mut body.var_debug_info {
                 if let VarDebugInfoContents::Place(p) = debuginfo.value {
                     if p.local == local && p.projection.is_empty() {
@@ -45,7 +45,7 @@ struct LocalUseVisitor {
     local_assignment_locations: IndexVec<Local, Option<Location>>,
 }
 
-fn find_optimization_oportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> {
+fn find_optimization_opportunities<'tcx>(body: &Body<'tcx>) -> Vec<(Local, Constant<'tcx>)> {
     let mut visitor = LocalUseVisitor {
         local_mutating_uses: IndexVec::from_elem(0, &body.local_decls),
         local_assignment_locations: IndexVec::from_elem(None, &body.local_decls),
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index c0146e3efb0..7f995c69a48 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -7,7 +7,7 @@ use rustc_const_eval::const_eval::CheckAlignment;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{IndexSlice, IndexVec};
+use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
 };
@@ -18,13 +18,12 @@ use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisi
 use rustc_span::{def_id::DefId, Span, DUMMY_SP};
 use rustc_target::abi::{self, Align, HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi as CallAbi;
-use rustc_trait_selection::traits;
 
 use crate::MirPass;
 use rustc_const_eval::interpret::{
-    self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame,
-    ImmTy, Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer,
-    Scalar, StackPopCleanup,
+    self, compile_time_machine, AllocId, ConstAllocation, ConstValue, Frame, ImmTy, Immediate,
+    InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar,
+    StackPopCleanup,
 };
 
 /// The maximum number of bytes that we'll allocate space for a local or the return value.
@@ -84,42 +83,6 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
             return;
         }
 
-        // Check if it's even possible to satisfy the 'where' clauses
-        // for this item.
-        // This branch will never be taken for any normal function.
-        // However, it's possible to `#!feature(trivial_bounds)]` to write
-        // a function with impossible to satisfy clauses, e.g.:
-        // `fn foo() where String: Copy {}`
-        //
-        // We don't usually need to worry about this kind of case,
-        // since we would get a compilation error if the user tried
-        // to call it. However, since we can do const propagation
-        // even without any calls to the function, we need to make
-        // sure that it even makes sense to try to evaluate the body.
-        // If there are unsatisfiable where clauses, then all bets are
-        // off, and we just give up.
-        //
-        // We manually filter the predicates, skipping anything that's not
-        // "global". We are in a potentially generic context
-        // (e.g. we are evaluating a function without substituting generic
-        // parameters, so this filtering serves two purposes:
-        //
-        // 1. We skip evaluating any predicates that we would
-        // never be able prove are unsatisfiable (e.g. `<T as Foo>`
-        // 2. We avoid trying to normalize predicates involving generic
-        // parameters (e.g. `<T as Foo>::MyItem`). This can confuse
-        // the normalization code (leading to cycle errors), since
-        // it's usually never invoked in this way.
-        let predicates = tcx
-            .predicates_of(def_id.to_def_id())
-            .predicates
-            .iter()
-            .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
-        if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
-            trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id);
-            return;
-        }
-
         trace!("ConstProp starting for {:?}", def_id);
 
         let dummy_body = &Body::new(
@@ -428,7 +391,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     /// Returns the value, if any, of evaluating `c`.
     fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<OpTy<'tcx>> {
         // FIXME we need to revisit this for #67176
-        if c.needs_subst() {
+        if c.has_param() {
             return None;
         }
 
@@ -501,16 +464,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
                 return None;
             }
-            // Do not try creating references, nor any types with potentially-complex
-            // invariants. This avoids an issue where checking validity would do a
-            // bunch of work generating a nice message about the invariant violation,
-            // only to not show it to anyone (since this isn't the lint).
-            Rvalue::Cast(CastKind::Transmute, op, dst_ty) if !dst_ty.is_primitive() => {
-                trace!("skipping Transmute of {:?} to {:?}", op, dst_ty);
-
-                return None;
-            }
-
             // There's no other checking to do at this time.
             Rvalue::Aggregate(..)
             | Rvalue::Use(..)
@@ -527,7 +480,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
 
         // FIXME we need to revisit this for #67176
-        if rvalue.needs_subst() {
+        if rvalue.has_param() {
             return None;
         }
         if !rvalue
@@ -628,18 +581,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
 
         trace!("attempting to replace {:?} with {:?}", rval, value);
-        if let Err(e) = self.ecx.const_validate_operand(
-            value,
-            vec![],
-            // FIXME: is ref tracking too expensive?
-            // FIXME: what is the point of ref tracking if we do not even check the tracked refs?
-            &mut interpret::RefTracking::empty(),
-            CtfeValidationMode::Regular,
-        ) {
-            trace!("validation error, attempt failed: {:?}", e);
-            return;
-        }
-
         // FIXME> figure out what to do when read_immediate_raw fails
         let imm = self.ecx.read_immediate_raw(value).ok();
 
@@ -773,13 +714,22 @@ impl CanConstProp {
     }
 }
 
-impl Visitor<'_> for CanConstProp {
+impl<'tcx> Visitor<'tcx> for CanConstProp {
+    fn visit_place(&mut self, place: &Place<'tcx>, mut context: PlaceContext, loc: Location) {
+        use rustc_middle::mir::visit::PlaceContext::*;
+
+        // Dereferencing just read the addess of `place.local`.
+        if place.projection.first() == Some(&PlaceElem::Deref) {
+            context = NonMutatingUse(NonMutatingUseContext::Copy);
+        }
+
+        self.visit_local(place.local, context, loc);
+        self.visit_projection(place.as_ref(), context, loc);
+    }
+
     fn visit_local(&mut self, local: Local, context: PlaceContext, _: Location) {
         use rustc_middle::mir::visit::PlaceContext::*;
         match context {
-            // Projections are fine, because `&mut foo.x` will be caught by
-            // `MutatingUseContext::Borrow` elsewhere.
-            MutatingUse(MutatingUseContext::Projection)
             // These are just stores, where the storing is not propagatable, but there may be later
             // mutations of the same local via `Store`
             | MutatingUse(MutatingUseContext::Call)
@@ -810,7 +760,7 @@ impl Visitor<'_> for CanConstProp {
             NonMutatingUse(NonMutatingUseContext::Copy)
             | NonMutatingUse(NonMutatingUseContext::Move)
             | NonMutatingUse(NonMutatingUseContext::Inspect)
-            | NonMutatingUse(NonMutatingUseContext::Projection)
+            | NonMutatingUse(NonMutatingUseContext::PlaceMention)
             | NonUse(_) => {}
 
             // These could be propagated with a smarter analysis or just some careful thinking about
@@ -826,9 +776,11 @@ impl Visitor<'_> for CanConstProp {
             | NonMutatingUse(NonMutatingUseContext::AddressOf)
             | MutatingUse(MutatingUseContext::Borrow)
             | MutatingUse(MutatingUseContext::AddressOf) => {
-                trace!("local {:?} can't be propagaged because it's used: {:?}", local, context);
+                trace!("local {:?} can't be propagated because it's used: {:?}", local, context);
                 self.can_const_prop[local] = ConstPropMode::NoPropagation;
             }
+            MutatingUse(MutatingUseContext::Projection)
+            | NonMutatingUse(NonMutatingUseContext::Projection) => bug!("visit_place should not pass {context:?} for {local:?}"),
         }
     }
 }
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 3a105a2abae..a4049d08d7b 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -281,7 +281,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     /// Returns the value, if any, of evaluating `c`.
     fn eval_constant(&mut self, c: &Constant<'tcx>, location: Location) -> Option<OpTy<'tcx>> {
         // FIXME we need to revisit this for #67176
-        if c.needs_subst() {
+        if c.has_param() {
             return None;
         }
 
@@ -474,7 +474,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
 
         // FIXME we need to revisit this for #67176
-        if rvalue.needs_subst() {
+        if rvalue.has_param() {
             return None;
         }
         if !rvalue.ty(self.local_decls(), self.tcx).is_sized(self.tcx, self.param_env) {
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index c155048c98b..3922ed2fbf7 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -1,5 +1,5 @@
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::IndexSlice;
+use rustc_index::IndexSlice;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 7391a77b0a6..986d2fd190d 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::graph::dominators::{self, Dominators};
 use rustc_data_structures::graph::{self, GraphSuccessors, WithNumNodes, WithStartNode};
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{IndexSlice, IndexVec};
+use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::{self, BasicBlock, BasicBlockData, Terminator, TerminatorKind};
 
@@ -111,7 +111,7 @@ impl CoverageGraph {
                         if predecessors.len() > 1 {
                             "predecessors.len() > 1".to_owned()
                         } else {
-                            format!("bb {} is not in precessors: {:?}", bb.index(), predecessors)
+                            format!("bb {} is not in predecessors: {:?}", bb.index(), predecessors)
                         }
                     );
                 }
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index 5ecb2d6a631..076e714d703 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -16,7 +16,7 @@ use crate::MirPass;
 
 use rustc_data_structures::graph::WithNumNodes;
 use rustc_data_structures::sync::Lrc;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
 use rustc_middle::hir;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::coverage::*;
@@ -514,7 +514,7 @@ fn make_code_region(
         // Extend an empty span by one character so the region will be counted.
         let CharPos(char_pos) = start_col;
         if span.hi() == body_span.hi() {
-            start_col = CharPos(char_pos - 1);
+            start_col = CharPos(char_pos.saturating_sub(1));
         } else {
             end_col = CharPos(char_pos + 1);
         }
@@ -577,5 +577,10 @@ fn get_body_span<'tcx>(
 fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>) -> u64 {
     // FIXME(cjgillot) Stop hashing HIR manually here.
     let owner = hir_body.id().hir_id.owner;
-    tcx.hir_owner_nodes(owner).unwrap().opt_hash_including_bodies.unwrap().to_smaller_hash()
+    tcx.hir_owner_nodes(owner)
+        .unwrap()
+        .opt_hash_including_bodies
+        .unwrap()
+        .to_smaller_hash()
+        .as_u64()
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index 3bd7f31b45d..bf01b45eb40 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -164,7 +164,6 @@ fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {
 /// whether that means const mir or runtime mir. For `const fn` this opts for runtime
 /// mir.
 fn mir_body(tcx: TyCtxt<'_>, def_id: DefId) -> &mir::Body<'_> {
-    let id = ty::WithOptConstParam::unknown(def_id);
-    let def = ty::InstanceDef::Item(id);
+    let def = ty::InstanceDef::Item(def_id);
     tcx.instance_mir(def)
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 0f6c06e370b..83a335197b3 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -34,7 +34,7 @@ use coverage_test_macros::let_bcb;
 use itertools::Itertools;
 use rustc_data_structures::graph::WithNumNodes;
 use rustc_data_structures::graph::WithSuccessors;
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index d4db7e2de40..254b704f9fc 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -70,22 +70,6 @@ struct ConstAnalysis<'a, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
 }
 
-impl<'tcx> ConstAnalysis<'_, 'tcx> {
-    fn eval_discriminant(
-        &self,
-        enum_ty: Ty<'tcx>,
-        variant_index: VariantIdx,
-    ) -> Option<ScalarTy<'tcx>> {
-        if !enum_ty.is_enum() {
-            return None;
-        }
-        let discr = enum_ty.discriminant_for_variant(self.tcx, variant_index)?;
-        let discr_layout = self.tcx.layout_of(self.param_env.and(discr.ty)).ok()?;
-        let discr_value = Scalar::try_from_uint(discr.val, discr_layout.size)?;
-        Some(ScalarTy(discr_value, discr.ty))
-    }
-}
-
 impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
     type Value = FlatSet<ScalarTy<'tcx>>;
 
@@ -126,59 +110,55 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
                 // we must make sure that all `target as Variant#i` are `Top`.
                 state.flood(target.as_ref(), self.map());
 
-                if let Some(target_idx) = self.map().find(target.as_ref()) {
-                    let (variant_target, variant_index) = match **kind {
-                        AggregateKind::Tuple | AggregateKind::Closure(..) => {
-                            (Some(target_idx), None)
-                        }
-                        AggregateKind::Adt(def_id, variant_index, ..) => {
-                            match self.tcx.def_kind(def_id) {
-                                DefKind::Struct => (Some(target_idx), None),
-                                DefKind::Enum => (
-                                    self.map.apply(target_idx, TrackElem::Variant(variant_index)),
-                                    Some(variant_index),
-                                ),
-                                _ => (None, None),
-                            }
-                        }
-                        _ => (None, None),
-                    };
-                    if let Some(variant_target_idx) = variant_target {
-                        for (field_index, operand) in operands.iter().enumerate() {
-                            if let Some(field) = self.map().apply(
-                                variant_target_idx,
-                                TrackElem::Field(FieldIdx::from_usize(field_index)),
-                            ) {
-                                let result = self.handle_operand(operand, state);
-                                state.insert_idx(field, result, self.map());
-                            }
+                let Some(target_idx) = self.map().find(target.as_ref()) else { return };
+
+                let (variant_target, variant_index) = match **kind {
+                    AggregateKind::Tuple | AggregateKind::Closure(..) => (Some(target_idx), None),
+                    AggregateKind::Adt(def_id, variant_index, ..) => {
+                        match self.tcx.def_kind(def_id) {
+                            DefKind::Struct => (Some(target_idx), None),
+                            DefKind::Enum => (
+                                self.map.apply(target_idx, TrackElem::Variant(variant_index)),
+                                Some(variant_index),
+                            ),
+                            _ => return,
                         }
                     }
-                    if let Some(variant_index) = variant_index
-                        && let Some(discr_idx) = self.map().apply(target_idx, TrackElem::Discriminant)
-                    {
-                        // We are assigning the discriminant as part of an aggregate.
-                        // This discriminant can only alias a variant field's value if the operand
-                        // had an invalid value for that type.
-                        // Using invalid values is UB, so we are allowed to perform the assignment
-                        // without extra flooding.
-                        let enum_ty = target.ty(self.local_decls, self.tcx).ty;
-                        if let Some(discr_val) = self.eval_discriminant(enum_ty, variant_index) {
-                            state.insert_value_idx(discr_idx, FlatSet::Elem(discr_val), &self.map);
+                    _ => return,
+                };
+                if let Some(variant_target_idx) = variant_target {
+                    for (field_index, operand) in operands.iter().enumerate() {
+                        if let Some(field) = self.map().apply(
+                            variant_target_idx,
+                            TrackElem::Field(FieldIdx::from_usize(field_index)),
+                        ) {
+                            let result = self.handle_operand(operand, state);
+                            state.insert_idx(field, result, self.map());
                         }
                     }
                 }
+                if let Some(variant_index) = variant_index
+                    && let Some(discr_idx) = self.map().apply(target_idx, TrackElem::Discriminant)
+                {
+                    // We are assigning the discriminant as part of an aggregate.
+                    // This discriminant can only alias a variant field's value if the operand
+                    // had an invalid value for that type.
+                    // Using invalid values is UB, so we are allowed to perform the assignment
+                    // without extra flooding.
+                    let enum_ty = target.ty(self.local_decls, self.tcx).ty;
+                    if let Some(discr_val) = self.eval_discriminant(enum_ty, variant_index) {
+                        state.insert_value_idx(discr_idx, FlatSet::Elem(discr_val), &self.map);
+                    }
+                }
             }
             Rvalue::CheckedBinaryOp(op, box (left, right)) => {
                 // Flood everything now, so we can use `insert_value_idx` directly later.
                 state.flood(target.as_ref(), self.map());
 
-                let target = self.map().find(target.as_ref());
+                let Some(target) = self.map().find(target.as_ref()) else { return };
 
-                let value_target = target
-                    .and_then(|target| self.map().apply(target, TrackElem::Field(0_u32.into())));
-                let overflow_target = target
-                    .and_then(|target| self.map().apply(target, TrackElem::Field(1_u32.into())));
+                let value_target = self.map().apply(target, TrackElem::Field(0_u32.into()));
+                let overflow_target = self.map().apply(target, TrackElem::Field(1_u32.into()));
 
                 if value_target.is_some() || overflow_target.is_some() {
                     let (val, overflow) = self.binary_op(state, *op, left, right);
@@ -323,7 +303,7 @@ impl<'tcx> std::fmt::Debug for ScalarTy<'tcx> {
 
 impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
     pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map) -> Self {
-        let param_env = tcx.param_env(body.source.def_id());
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         Self {
             map,
             tcx,
@@ -351,7 +331,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
             }
             (FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
             (_, _) => {
-                // Could attempt some algebraic simplifcations here.
+                // Could attempt some algebraic simplifications here.
                 (FlatSet::Top, FlatSet::Top)
             }
         }
@@ -377,6 +357,20 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
         }
     }
 
+    fn eval_discriminant(
+        &self,
+        enum_ty: Ty<'tcx>,
+        variant_index: VariantIdx,
+    ) -> Option<ScalarTy<'tcx>> {
+        if !enum_ty.is_enum() {
+            return None;
+        }
+        let discr = enum_ty.discriminant_for_variant(self.tcx, variant_index)?;
+        let discr_layout = self.tcx.layout_of(self.param_env.and(discr.ty)).ok()?;
+        let discr_value = Scalar::try_from_uint(discr.val, discr_layout.size)?;
+        Some(ScalarTy(discr_value, discr.ty))
+    }
+
     fn wrap_scalar(&self, scalar: Scalar, ty: Ty<'tcx>) -> FlatSet<ScalarTy<'tcx>> {
         FlatSet::Elem(ScalarTy(scalar, ty))
     }
@@ -520,21 +514,6 @@ impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> {
             _ => (),
         }
     }
-
-    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
-        match rvalue {
-            Rvalue::Discriminant(place) => {
-                match self.state.get_discr(place.as_ref(), self.visitor.map) {
-                    FlatSet::Top => (),
-                    FlatSet::Elem(value) => {
-                        self.visitor.before_effect.insert((location, *place), value);
-                    }
-                    FlatSet::Bottom => (),
-                }
-            }
-            _ => self.super_rvalue(rvalue, location),
-        }
-    }
 }
 
 struct DummyMachine;
diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
index 18c407b42d3..7bc5183a00a 100644
--- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs
+++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs
@@ -54,11 +54,10 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
                 | StatementKind::Coverage(_)
                 | StatementKind::Intrinsic(_)
                 | StatementKind::ConstEvalCounter
+                | StatementKind::PlaceMention(_)
                 | StatementKind::Nop => (),
 
-                StatementKind::FakeRead(_)
-                | StatementKind::PlaceMention(_)
-                | StatementKind::AscribeUserType(_, _) => {
+                StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
                     bug!("{:?} not found in this MIR phase!", &statement.kind)
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index b8a5b92be4a..a39026751a7 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -1,5 +1,5 @@
 use crate::MirPass;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 39164917770..78758e2db28 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -69,7 +69,7 @@
 //!   of this is that such liveness analysis can report more accurate results about whole locals at
 //!   a time. For example, consider:
 //!
-//!   ```ignore (syntax-highliting-only)
+//!   ```ignore (syntax-highlighting-only)
 //!   _1 = u;
 //!   // unrelated code
 //!   _1.f1 = v;
@@ -360,7 +360,7 @@ struct FilterInformation<'a, 'body, 'alloc, 'tcx> {
 }
 
 // We first implement some utility functions which we will expose removing candidates according to
-// different needs. Throughout the livenss filtering, the `candidates` are only ever accessed
+// different needs. Throughout the liveness filtering, the `candidates` are only ever accessed
 // through these methods, and not directly.
 impl<'alloc> Candidates<'alloc> {
     /// Just `Vec::retain`, but the condition is inverted and we add debugging output
@@ -582,10 +582,9 @@ impl WriteInfo {
             | StatementKind::Nop
             | StatementKind::Coverage(_)
             | StatementKind::StorageLive(_)
-            | StatementKind::StorageDead(_) => (),
-            StatementKind::FakeRead(_)
-            | StatementKind::AscribeUserType(_, _)
-            | StatementKind::PlaceMention(_) => {
+            | StatementKind::StorageDead(_)
+            | StatementKind::PlaceMention(_) => (),
+            StatementKind::FakeRead(_) | StatementKind::AscribeUserType(_, _) => {
                 bug!("{:?} not found in this MIR phase", statement)
             }
         }
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 85623499439..f31653caa49 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -4,7 +4,7 @@
 
 use crate::MirPass;
 use rustc_hir::def_id::DefId;
-use rustc_index::vec::Idx;
+use rustc_index::Idx;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index a702113bd99..98e7a519c20 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -1,7 +1,7 @@
 use crate::deref_separator::deref_finder;
 use crate::MirPass;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_index::bit_set::BitSet;
+use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
@@ -24,7 +24,7 @@ use std::fmt;
 /// In general, the compiler cannot determine at compile time whether a destructor will run or not.
 ///
 /// At a high level, this pass refines Drop to only run the destructor if the
-/// target is initialized. The way this is achievied is by inserting drop flags for every variable
+/// target is initialized. The way this is achieved is by inserting drop flags for every variable
 /// that may be dropped, and then using those flags to determine whether a destructor should run.
 /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or
 /// "drop shim" for the type of the dropped place.
@@ -84,12 +84,13 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
 
             let reachable = traversal::reachable_as_bitset(body);
 
+            let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths);
             ElaborateDropsCtxt {
                 tcx,
                 body,
                 env: &env,
                 init_data: InitializationData { inits, uninits },
-                drop_flags: Default::default(),
+                drop_flags,
                 patch: MirPatch::new(body),
                 un_derefer: un_derefer,
                 reachable,
@@ -293,7 +294,7 @@ struct ElaborateDropsCtxt<'a, 'tcx> {
     body: &'a Body<'tcx>,
     env: &'a MoveDataParamEnv<'tcx>,
     init_data: InitializationData<'a, 'tcx>,
-    drop_flags: FxHashMap<MovePathIndex, Local>,
+    drop_flags: IndexVec<MovePathIndex, Option<Local>>,
     patch: MirPatch<'tcx>,
     un_derefer: UnDerefer<'tcx>,
     reachable: BitSet<BasicBlock>,
@@ -312,11 +313,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         let tcx = self.tcx;
         let patch = &mut self.patch;
         debug!("create_drop_flag({:?})", self.body.span);
-        self.drop_flags.entry(index).or_insert_with(|| patch.new_internal(tcx.types.bool, span));
+        self.drop_flags[index].get_or_insert_with(|| patch.new_internal(tcx.types.bool, span));
     }
 
     fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
-        self.drop_flags.get(&index).map(|t| Place::from(*t))
+        self.drop_flags[index].map(Place::from)
     }
 
     /// create a patch that elaborates all drops in the input
@@ -365,7 +366,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                     if maybe_dead {
                         self.tcx.sess.delay_span_bug(
                             terminator.source_info.span,
-                            &format!(
+                            format!(
                                 "drop of untracked, uninitialized value {:?}, place {:?} ({:?})",
                                 bb, place, path
                             ),
@@ -439,7 +440,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             ) {
                                 self.tcx.sess.delay_span_bug(
                                     terminator.source_info.span,
-                                    &format!("drop of untracked value {:?}", bb),
+                                    format!("drop of untracked value {:?}", bb),
                                 );
                             }
                             // A drop and replace behind a pointer/array/whatever.
@@ -463,7 +464,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
     }
 
     fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex, val: DropFlagState) {
-        if let Some(&flag) = self.drop_flags.get(&path) {
+        if let Some(flag) = self.drop_flags[path] {
             let span = self.patch.source_info_for_location(self.body, loc).span;
             let val = self.constant_bool(span, val.value());
             self.patch.add_assign(loc, Place::from(flag), val);
@@ -474,7 +475,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         let loc = Location::START;
         let span = self.patch.source_info_for_location(self.body, loc).span;
         let false_ = self.constant_bool(span, false);
-        for flag in self.drop_flags.values() {
+        for flag in self.drop_flags.iter().flatten() {
             self.patch.add_assign(loc, Place::from(*flag), false_.clone());
         }
     }
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index c9b24adba0c..db68adc8bc9 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -48,7 +48,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
         return false;
     }
 
-    let body = &*tcx.mir_built(ty::WithOptConstParam::unknown(local_def_id)).borrow();
+    let body = &*tcx.mir_built(local_def_id).borrow();
 
     let body_ty = tcx.type_of(def_id).skip_binder();
     let body_abi = match body_ty.kind() {
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 8601c1b2d71..f26c6de9648 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -3,7 +3,7 @@ use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, EarlyBinder, GenericArgKind, PredicateKind, SubstsRef, Ty, TyCtxt};
+use rustc_middle::ty::{self, EarlyBinder, PredicateKind, SubstsRef, Ty, TyCtxt};
 use rustc_session::lint::builtin::FUNCTION_ITEM_REFERENCES;
 use rustc_span::{symbol::sym, Span};
 use rustc_target::spec::abi::Abi;
@@ -45,14 +45,12 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
                 // Handle calls to `transmute`
                 if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
                     let arg_ty = args[0].ty(self.body, self.tcx);
-                    for generic_inner_ty in arg_ty.walk() {
-                        if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
-                            if let Some((fn_id, fn_substs)) =
-                                FunctionItemRefChecker::is_fn_ref(inner_ty)
-                            {
-                                let span = self.nth_arg_span(&args, 0);
-                                self.emit_lint(fn_id, fn_substs, source_info, span);
-                            }
+                    for inner_ty in arg_ty.walk().filter_map(|arg| arg.as_type()) {
+                        if let Some((fn_id, fn_substs)) =
+                            FunctionItemRefChecker::is_fn_ref(inner_ty)
+                        {
+                            let span = self.nth_arg_span(&args, 0);
+                            self.emit_lint(fn_id, fn_substs, source_info, span);
                         }
                     }
                 } else {
@@ -82,24 +80,22 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
                 let arg_defs = self.tcx.fn_sig(def_id).subst_identity().skip_binder().inputs();
                 for (arg_num, arg_def) in arg_defs.iter().enumerate() {
                     // For all types reachable from the argument type in the fn sig
-                    for generic_inner_ty in arg_def.walk() {
-                        if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
-                            // If the inner type matches the type bound by `Pointer`
-                            if inner_ty == bound_ty {
-                                // Do a substitution using the parameters from the callsite
-                                let subst_ty = EarlyBinder(inner_ty).subst(self.tcx, substs_ref);
-                                if let Some((fn_id, fn_substs)) =
-                                    FunctionItemRefChecker::is_fn_ref(subst_ty)
-                                {
-                                    let mut span = self.nth_arg_span(args, arg_num);
-                                    if span.from_expansion() {
-                                        // The operand's ctxt wouldn't display the lint since it's inside a macro so
-                                        // we have to use the callsite's ctxt.
-                                        let callsite_ctxt = span.source_callsite().ctxt();
-                                        span = span.with_ctxt(callsite_ctxt);
-                                    }
-                                    self.emit_lint(fn_id, fn_substs, source_info, span);
+                    for inner_ty in arg_def.walk().filter_map(|arg| arg.as_type()) {
+                        // If the inner type matches the type bound by `Pointer`
+                        if inner_ty == bound_ty {
+                            // Do a substitution using the parameters from the callsite
+                            let subst_ty = EarlyBinder(inner_ty).subst(self.tcx, substs_ref);
+                            if let Some((fn_id, fn_substs)) =
+                                FunctionItemRefChecker::is_fn_ref(subst_ty)
+                            {
+                                let mut span = self.nth_arg_span(args, arg_num);
+                                if span.from_expansion() {
+                                    // The operand's ctxt wouldn't display the lint since it's inside a macro so
+                                    // we have to use the callsite's ctxt.
+                                    let callsite_ctxt = span.source_callsite().ctxt();
+                                    span = span.with_ctxt(callsite_ctxt);
                                 }
+                                self.emit_lint(fn_id, fn_substs, source_info, span);
                             }
                         }
                     }
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 4c4423721fb..9e16c400f14 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -59,7 +59,7 @@ use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::GeneratorKind;
 use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet};
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::dump_mir;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
@@ -865,7 +865,7 @@ fn sanitize_witness<'tcx>(
         _ => {
             tcx.sess.delay_span_bug(
                 body.span,
-                &format!("unexpected generator witness type {:?}", witness.kind()),
+                format!("unexpected generator witness type {:?}", witness.kind()),
             );
             return;
         }
@@ -1150,7 +1150,7 @@ fn insert_panic_block<'tcx>(
             literal: ConstantKind::from_bool(tcx, false),
         })),
         expected: true,
-        msg: message,
+        msg: Box::new(message),
         target: assert_block,
         unwind: UnwindAction::Continue,
     };
@@ -1399,7 +1399,7 @@ pub(crate) fn mir_generator_witnesses<'tcx>(
 ) -> GeneratorLayout<'tcx> {
     assert!(tcx.sess.opts.unstable_opts.drop_tracking_mir);
 
-    let (body, _) = tcx.mir_promoted(ty::WithOptConstParam::unknown(def_id));
+    let (body, _) = tcx.mir_promoted(def_id);
     let body = body.borrow();
     let body = &*body;
 
@@ -1451,8 +1451,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
                 )
             }
             _ => {
-                tcx.sess
-                    .delay_span_bug(body.span, &format!("unexpected generator type {}", gen_ty));
+                tcx.sess.delay_span_bug(body.span, format!("unexpected generator type {}", gen_ty));
                 return;
             }
         };
@@ -1800,7 +1799,7 @@ fn check_must_not_suspend_ty<'tcx>(
         // FIXME: support adding the attribute to TAITs
         ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
             let mut has_emitted = false;
-            for &(predicate, _) in tcx.explicit_item_bounds(def) {
+            for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() {
                 // We only look at the `DefId`, so it is safe to skip the binder here.
                 if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) =
                     predicate.kind().skip_binder()
@@ -1869,7 +1868,7 @@ fn check_must_not_suspend_ty<'tcx>(
                 },
             )
         }
-        // If drop tracking is enabled, we want to look through references, since the referrent
+        // If drop tracking is enabled, we want to look through references, since the referent
         // may not be considered live across the await point.
         ty::Ref(_region, ty, _mutability) => {
             let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 1525933aee3..71bdfd5aae1 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -3,7 +3,7 @@ use crate::deref_separator::deref_finder;
 use rustc_attr::InlineAttr;
 use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::Idx;
+use rustc_index::Idx;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
@@ -26,8 +26,6 @@ const CALL_PENALTY: usize = 25;
 const LANDINGPAD_PENALTY: usize = 50;
 const RESUME_PENALTY: usize = 45;
 
-const UNKNOWN_SIZE_COST: usize = 10;
-
 const TOP_DOWN_DEPTH_LIMIT: usize = 5;
 
 pub struct Inline;
@@ -464,12 +462,6 @@ impl<'tcx> Inliner<'tcx> {
             }
         }
 
-        // Count up the cost of local variables and temps, if we know the size
-        // use that, otherwise we use a moderately-large dummy cost.
-        for v in callee_body.vars_and_temps_iter() {
-            checker.visit_local_decl(v, &callee_body.local_decls[v]);
-        }
-
         // Abort if type validation found anything fishy.
         checker.validation?;
 
@@ -764,14 +756,6 @@ impl<'tcx> Inliner<'tcx> {
     }
 }
 
-fn type_size_of<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    ty: Ty<'tcx>,
-) -> Option<u64> {
-    tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes())
-}
-
 /// Verify that the callee body is compatible with the caller.
 ///
 /// This visitor mostly computes the inlining cost,
@@ -845,24 +829,6 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
         self.super_terminator(terminator, location);
     }
 
-    /// Count up the cost of local variables and temps, if we know the size
-    /// use that, otherwise we use a moderately-large dummy cost.
-    fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
-        let tcx = self.tcx;
-        let ptr_size = tcx.data_layout.pointer_size.bytes();
-
-        let ty = self.instance.subst_mir(tcx, &local_decl.ty);
-        // Cost of the var is the size in machine-words, if we know
-        // it.
-        if let Some(size) = type_size_of(tcx, self.param_env, ty) {
-            self.cost += ((size + ptr_size - 1) / ptr_size) as usize;
-        } else {
-            self.cost += UNKNOWN_SIZE_COST;
-        }
-
-        self.super_local_decl(local, local_decl)
-    }
-
     /// This method duplicates code from MIR validation in an attempt to detect type mismatches due
     /// to normalization failure.
     fn visit_projection_elem(
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 8aa3c23d019..6046c3876be 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -13,7 +13,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
     tcx: TyCtxt<'tcx>,
     (root, target): (ty::Instance<'tcx>, LocalDefId),
 ) -> bool {
-    trace!(%root, target = %tcx.def_path_str(target.to_def_id()));
+    trace!(%root, target = %tcx.def_path_str(target));
     let param_env = tcx.param_env_reveal_all_normalized(target);
     assert_ne!(
         root.def_id().expect_local(),
@@ -92,7 +92,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>(
                     // FIXME: A not fully substituted drop shim can cause ICEs if one attempts to
                     // have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this
                     // needs some more analysis.
-                    if callee.needs_subst() {
+                    if callee.has_param() {
                         continue;
                     }
                 }
@@ -148,8 +148,7 @@ pub(crate) fn mir_inliner_callees<'tcx>(
     let guard;
     let body = match (instance, instance.def_id().as_local()) {
         (InstanceDef::Item(_), Some(def_id)) => {
-            let def = ty::WithOptConstParam::unknown(def_id);
-            steal = tcx.mir_promoted(def).0;
+            steal = tcx.mir_promoted(def_id).0;
             guard = steal.borrow();
             &*guard
         }
diff --git a/compiler/rustc_mir_transform/src/instcombine.rs b/compiler/rustc_mir_transform/src/instcombine.rs
index 3d06a0a495f..432852a1fdd 100644
--- a/compiler/rustc_mir_transform/src/instcombine.rs
+++ b/compiler/rustc_mir_transform/src/instcombine.rs
@@ -1,11 +1,9 @@
 //! Performs various peephole optimizations.
 
+use crate::simplify::combine_duplicate_switch_targets;
 use crate::MirPass;
 use rustc_hir::Mutability;
-use rustc_middle::mir::{
-    BinOp, Body, CastKind, Constant, ConstantKind, LocalDecls, Operand, Place, ProjectionElem,
-    Rvalue, SourceInfo, Statement, StatementKind, SwitchTargets, Terminator, TerminatorKind, UnOp,
-};
+use rustc_middle::mir::*;
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::util::IntTypeExt;
 use rustc_middle::ty::{self, ParamEnv, SubstsRef, Ty, TyCtxt};
@@ -46,7 +44,7 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
                 &mut block.terminator.as_mut().unwrap(),
                 &mut block.statements,
             );
-            ctx.combine_duplicate_switch_targets(&mut block.terminator.as_mut().unwrap());
+            combine_duplicate_switch_targets(block.terminator.as_mut().unwrap());
         }
     }
 }
@@ -264,19 +262,6 @@ impl<'tcx> InstCombineContext<'tcx, '_> {
         terminator.kind = TerminatorKind::Goto { target: destination_block };
     }
 
-    fn combine_duplicate_switch_targets(&self, terminator: &mut Terminator<'tcx>) {
-        let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind
-        else { return };
-
-        let otherwise = targets.otherwise();
-        if targets.iter().any(|t| t.1 == otherwise) {
-            *targets = SwitchTargets::new(
-                targets.iter().filter(|t| t.1 != otherwise),
-                targets.otherwise(),
-            );
-        }
-    }
-
     fn combine_intrinsic_assert(
         &self,
         terminator: &mut Terminator<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 9447a2ff040..430a6f6cef5 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -120,7 +120,7 @@ impl EnumSizeOpt {
     fn optim<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let mut alloc_cache = FxHashMap::default();
         let body_did = body.source.def_id();
-        let param_env = tcx.param_env(body_did);
+        let param_env = tcx.param_env_reveal_all_normalized(body_did);
 
         let blocks = body.basic_blocks.as_mut();
         let local_decls = &mut body.local_decls;
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index fc12d423cb0..8d9a22ea30d 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -23,18 +23,19 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::steal::Steal;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
 use rustc_middle::mir::visit::Visitor as _;
 use rustc_middle::mir::{
     traversal, AnalysisPhase, Body, ClearCrossCrate, ConstQualifs, Constant, LocalDecl, MirPass,
     MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo,
-    Statement, StatementKind, TerminatorKind,
+    Statement, StatementKind, TerminatorKind, START_BLOCK,
 };
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
 use rustc_span::sym;
+use rustc_trait_selection::traits;
 
 #[macro_use]
 mod pass_manager;
@@ -48,6 +49,7 @@ mod add_retag;
 mod check_const_item_mutation;
 mod check_packed_ref;
 pub mod check_unsafety;
+mod remove_place_mention;
 // This pass is public to allow external drivers to perform MIR cleanup
 pub mod cleanup_post_borrowck;
 mod const_debuginfo;
@@ -111,36 +113,17 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         mir_keys,
         mir_const,
-        mir_const_qualif: |tcx, def_id| {
-            if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
-                tcx.mir_const_qualif_const_arg(def)
-            } else {
-                mir_const_qualif(tcx, ty::WithOptConstParam::unknown(def_id))
-            }
-        },
-        mir_const_qualif_const_arg: |tcx, (did, param_did)| {
-            mir_const_qualif(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
-        },
+        mir_const_qualif,
         mir_promoted,
         mir_drops_elaborated_and_const_checked,
         mir_for_ctfe,
-        mir_for_ctfe_of_const_arg,
         mir_generator_witnesses: generator::mir_generator_witnesses,
         optimized_mir,
         is_mir_available,
         is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did),
         mir_callgraph_reachable: inline::cycle::mir_callgraph_reachable,
         mir_inliner_callees: inline::cycle::mir_inliner_callees,
-        promoted_mir: |tcx, def_id| {
-            if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
-                tcx.promoted_mir_of_const_arg(def)
-            } else {
-                promoted_mir(tcx, ty::WithOptConstParam::unknown(def_id))
-            }
-        },
-        promoted_mir_of_const_arg: |tcx, (did, param_did)| {
-            promoted_mir(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) })
-        },
+        promoted_mir,
         deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
         ..*providers
     };
@@ -234,8 +217,8 @@ fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
     set
 }
 
-fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> ConstQualifs {
-    let const_kind = tcx.hir().body_const_context(def.did);
+fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
+    let const_kind = tcx.hir().body_const_context(def);
 
     // No need to const-check a non-const `fn`.
     if const_kind.is_none() {
@@ -253,7 +236,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
         return Default::default();
     }
 
-    let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def.did) };
+    let ccx = check_consts::ConstCx { body, tcx, const_kind, param_env: tcx.param_env(def) };
 
     let mut validator = check_consts::check::Checker::new(&ccx);
     validator.check_body();
@@ -266,22 +249,14 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) ->
 /// Make MIR ready for const evaluation. This is run on all MIR, not just on consts!
 /// FIXME(oli-obk): it's unclear whether we still need this phase (and its corresponding query).
 /// We used to have this for pre-miri MIR based const eval.
-fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<Body<'_>> {
-    if let Some(def) = def.try_upgrade(tcx) {
-        return tcx.mir_const(def);
-    }
-
+fn mir_const(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
     // Unsafety check uses the raw mir, so make sure it is run.
     if !tcx.sess.opts.unstable_opts.thir_unsafeck {
-        if let Some(param_did) = def.const_param_did {
-            tcx.ensure_with_value().unsafety_check_result_for_const_arg((def.did, param_did));
-        } else {
-            tcx.ensure_with_value().unsafety_check_result(def.did);
-        }
+        tcx.ensure_with_value().unsafety_check_result(def);
     }
 
     // has_ffi_unwind_calls query uses the raw mir, so make sure it is run.
-    tcx.ensure_with_value().has_ffi_unwind_calls(def.did);
+    tcx.ensure_with_value().has_ffi_unwind_calls(def);
 
     let mut body = tcx.mir_built(def).steal();
 
@@ -296,7 +271,7 @@ fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<
             &Lint(check_const_item_mutation::CheckConstItemMutation),
             &Lint(function_item_references::FunctionItemReferences),
             // What we need to do constant evaluation.
-            &simplify::SimplifyCfg::new("initial"),
+            &simplify::SimplifyCfg::Initial,
             &rustc_peek::SanityCheck, // Just a lint
         ],
         None,
@@ -307,16 +282,12 @@ fn mir_const(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> &Steal<
 /// Compute the main MIR body and the list of MIR bodies of the promoteds.
 fn mir_promoted(
     tcx: TyCtxt<'_>,
-    def: ty::WithOptConstParam<LocalDefId>,
+    def: LocalDefId,
 ) -> (&Steal<Body<'_>>, &Steal<IndexVec<Promoted, Body<'_>>>) {
-    if let Some(def) = def.try_upgrade(tcx) {
-        return tcx.mir_promoted(def);
-    }
-
     // Ensure that we compute the `mir_const_qualif` for constants at
     // this point, before we steal the mir-const result.
     // Also this means promotion can rely on all const checks having been done.
-    let const_qualifs = tcx.mir_const_qualif_opt_const_arg(def);
+    let const_qualifs = tcx.mir_const_qualif(def);
     let mut body = tcx.mir_const(def).steal();
     if let Some(error_reported) = const_qualifs.tainted_by_errors {
         body.tainted_by_errors = Some(error_reported);
@@ -334,11 +305,7 @@ fn mir_promoted(
     pm::run_passes(
         tcx,
         &mut body,
-        &[
-            &promote_pass,
-            &simplify::SimplifyCfg::new("promote-consts"),
-            &coverage::InstrumentCoverage,
-        ],
+        &[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
         Some(MirPhase::Analysis(AnalysisPhase::Initial)),
     );
 
@@ -348,38 +315,22 @@ fn mir_promoted(
 
 /// Compute the MIR that is used during CTFE (and thus has no optimizations run on it)
 fn mir_for_ctfe(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &Body<'_> {
-    if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) {
-        tcx.mir_for_ctfe_of_const_arg(def)
-    } else {
-        tcx.arena.alloc(inner_mir_for_ctfe(tcx, ty::WithOptConstParam::unknown(def_id)))
-    }
+    tcx.arena.alloc(inner_mir_for_ctfe(tcx, def_id))
 }
 
-/// Same as `mir_for_ctfe`, but used to get the MIR of a const generic parameter.
-/// The docs on `WithOptConstParam` explain this a bit more, but the TLDR is that
-/// we'd get cycle errors with `mir_for_ctfe`, because typeck would need to typeck
-/// the const parameter while type checking the main body, which in turn would try
-/// to type check the main body again.
-fn mir_for_ctfe_of_const_arg(tcx: TyCtxt<'_>, (did, param_did): (LocalDefId, DefId)) -> &Body<'_> {
-    tcx.arena.alloc(inner_mir_for_ctfe(
-        tcx,
-        ty::WithOptConstParam { did, const_param_did: Some(param_did) },
-    ))
-}
-
-fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
+fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
     // FIXME: don't duplicate this between the optimized_mir/mir_for_ctfe queries
-    if tcx.is_constructor(def.did.to_def_id()) {
+    if tcx.is_constructor(def.to_def_id()) {
         // There's no reason to run all of the MIR passes on constructors when
         // we can just output the MIR we want directly. This also saves const
         // qualification and borrow checking the trouble of special casing
         // constructors.
-        return shim::build_adt_ctor(tcx, def.did.to_def_id());
+        return shim::build_adt_ctor(tcx, def.to_def_id());
     }
 
     let context = tcx
         .hir()
-        .body_const_context(def.did)
+        .body_const_context(def)
         .expect("mir_for_ctfe should not be used for runtime functions");
 
     let body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone();
@@ -417,29 +368,19 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
 /// Obtain just the main MIR (no promoteds) and run some cleanups on it. This also runs
 /// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't
 /// end up missing the source MIR due to stealing happening.
-fn mir_drops_elaborated_and_const_checked(
-    tcx: TyCtxt<'_>,
-    def: ty::WithOptConstParam<LocalDefId>,
-) -> &Steal<Body<'_>> {
-    if let Some(def) = def.try_upgrade(tcx) {
-        return tcx.mir_drops_elaborated_and_const_checked(def);
-    }
-
+fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
     if tcx.sess.opts.unstable_opts.drop_tracking_mir
-        && let DefKind::Generator = tcx.def_kind(def.did)
+        && let DefKind::Generator = tcx.def_kind(def)
     {
-        tcx.ensure_with_value().mir_generator_witnesses(def.did);
+        tcx.ensure_with_value().mir_generator_witnesses(def);
     }
-    let mir_borrowck = tcx.mir_borrowck_opt_const_arg(def);
+    let mir_borrowck = tcx.mir_borrowck(def);
 
-    let is_fn_like = tcx.def_kind(def.did).is_fn_like();
+    let is_fn_like = tcx.def_kind(def).is_fn_like();
     if is_fn_like {
-        let did = def.did.to_def_id();
-        let def = ty::WithOptConstParam::unknown(did);
-
         // Do not compute the mir call graph without said call graph actually being used.
         if inline::Inline.is_enabled(&tcx.sess) {
-            tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def));
+            tcx.ensure_with_value().mir_inliner_callees(ty::InstanceDef::Item(def.to_def_id()));
         }
     }
 
@@ -449,6 +390,50 @@ fn mir_drops_elaborated_and_const_checked(
         body.tainted_by_errors = Some(error_reported);
     }
 
+    // Check if it's even possible to satisfy the 'where' clauses
+    // for this item.
+    //
+    // This branch will never be taken for any normal function.
+    // However, it's possible to `#!feature(trivial_bounds)]` to write
+    // a function with impossible to satisfy clauses, e.g.:
+    // `fn foo() where String: Copy {}`
+    //
+    // We don't usually need to worry about this kind of case,
+    // since we would get a compilation error if the user tried
+    // to call it. However, since we optimize even without any
+    // calls to the function, we need to make sure that it even
+    // makes sense to try to evaluate the body.
+    //
+    // If there are unsatisfiable where clauses, then all bets are
+    // off, and we just give up.
+    //
+    // We manually filter the predicates, skipping anything that's not
+    // "global". We are in a potentially generic context
+    // (e.g. we are evaluating a function without substituting generic
+    // parameters, so this filtering serves two purposes:
+    //
+    // 1. We skip evaluating any predicates that we would
+    // never be able prove are unsatisfiable (e.g. `<T as Foo>`
+    // 2. We avoid trying to normalize predicates involving generic
+    // parameters (e.g. `<T as Foo>::MyItem`). This can confuse
+    // the normalization code (leading to cycle errors), since
+    // it's usually never invoked in this way.
+    let predicates = tcx
+        .predicates_of(body.source.def_id())
+        .predicates
+        .iter()
+        .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
+    if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) {
+        trace!("found unsatisfiable predicates for {:?}", body.source);
+        // Clear the body to only contain a single `unreachable` statement.
+        let bbs = body.basic_blocks.as_mut();
+        bbs.raw.truncate(1);
+        bbs[START_BLOCK].statements.clear();
+        bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable;
+        body.var_debug_info.clear();
+        body.local_decls.raw.truncate(body.arg_count + 1);
+    }
+
     run_analysis_to_runtime_passes(tcx, &mut body);
 
     tcx.alloc_steal_mir(body)
@@ -467,10 +452,7 @@ fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>
         pm::run_passes(
             tcx,
             body,
-            &[
-                &remove_uninit_drops::RemoveUninitDrops,
-                &simplify::SimplifyCfg::new("remove-false-edges"),
-            ],
+            &[&remove_uninit_drops::RemoveUninitDrops, &simplify::SimplifyCfg::RemoveFalseEdges],
             None,
         );
         check_consts::post_drop_elaboration::check_live_drops(tcx, &body); // FIXME: make this a MIR lint
@@ -492,7 +474,7 @@ fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     let passes: &[&dyn MirPass<'tcx>] = &[
         &cleanup_post_borrowck::CleanupPostBorrowck,
         &remove_noop_landing_pads::RemoveNoopLandingPads,
-        &simplify::SimplifyCfg::new("early-opt"),
+        &simplify::SimplifyCfg::EarlyOpt,
         &deref_separator::Derefer,
     ];
 
@@ -524,8 +506,11 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
 /// Returns the sequence of passes that do the initial cleanup of runtime MIR.
 fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let passes: &[&dyn MirPass<'tcx>] =
-        &[&lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::new("elaborate-drops")];
+    let passes: &[&dyn MirPass<'tcx>] = &[
+        &lower_intrinsics::LowerIntrinsics,
+        &remove_place_mention::RemovePlaceMention,
+        &simplify::SimplifyCfg::ElaborateDrops,
+    ];
 
     pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
 
@@ -551,7 +536,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &lower_slice_len::LowerSliceLenCalls, // has to be done before inlining, otherwise actual call will be almost always inlined. Also simple, so can just do first
             &unreachable_prop::UnreachablePropagation,
             &uninhabited_enum_branching::UninhabitedEnumBranching,
-            &o1(simplify::SimplifyCfg::new("after-uninhabited-enum-branching")),
+            &o1(simplify::SimplifyCfg::AfterUninhabitedEnumBranching),
             &inline::Inline,
             &remove_storage_markers::RemoveStorageMarkers,
             &remove_zsts::RemoveZsts,
@@ -564,23 +549,23 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &multiple_return_terminators::MultipleReturnTerminators,
             &instcombine::InstCombine,
             &separate_const_switch::SeparateConstSwitch,
-            &simplify::SimplifyLocals::new("before-const-prop"),
+            &simplify::SimplifyLocals::BeforeConstProp,
             &copy_prop::CopyProp,
             &const_prop::ConstProp,
             &dataflow_const_prop::DataflowConstProp,
             //
             // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0.
             &const_debuginfo::ConstDebugInfo,
-            &o1(simplify_branches::SimplifyConstCondition::new("after-const-prop")),
+            &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
             &early_otherwise_branch::EarlyOtherwiseBranch,
             &simplify_comparison_integral::SimplifyComparisonIntegral,
             &dead_store_elimination::DeadStoreElimination,
             &dest_prop::DestinationPropagation,
-            &o1(simplify_branches::SimplifyConstCondition::new("final")),
+            &o1(simplify_branches::SimplifyConstCondition::Final),
             &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
-            &o1(simplify::SimplifyCfg::new("final")),
+            &o1(simplify::SimplifyCfg::Final),
             &nrvo::RenameReturnPlace,
-            &simplify::SimplifyLocals::new("final"),
+            &simplify::SimplifyLocals::Final,
             &multiple_return_terminators::MultipleReturnTerminators,
             &deduplicate_blocks::DeduplicateBlocks,
             &large_enums::EnumSizeOpt { discrepancy: 128 },
@@ -595,7 +580,6 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
 /// Optimize the MIR and prepare it for codegen.
 fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> {
-    assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None);
     tcx.arena.alloc(inner_optimized_mir(tcx, did))
 }
 
@@ -617,8 +601,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
         Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other),
     }
     debug!("about to call mir_drops_elaborated...");
-    let body =
-        tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
+    let body = tcx.mir_drops_elaborated_and_const_checked(did).steal();
     let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst);
     debug!("body: {:#?}", body);
     run_optimization_passes(tcx, &mut body);
@@ -628,21 +611,15 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
 
 /// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for
 /// constant evaluation once all substitutions become known.
-fn promoted_mir(
-    tcx: TyCtxt<'_>,
-    def: ty::WithOptConstParam<LocalDefId>,
-) -> &IndexVec<Promoted, Body<'_>> {
-    if tcx.is_constructor(def.did.to_def_id()) {
+fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_>> {
+    if tcx.is_constructor(def.to_def_id()) {
         return tcx.arena.alloc(IndexVec::new());
     }
 
-    let tainted_by_errors = tcx.mir_borrowck_opt_const_arg(def).tainted_by_errors;
+    tcx.ensure_with_value().mir_borrowck(def);
     let mut promoted = tcx.mir_promoted(def).1.steal();
 
     for body in &mut promoted {
-        if let Some(error_reported) = tainted_by_errors {
-            body.tainted_by_errors = Some(error_reported);
-        }
         run_analysis_to_runtime_passes(tcx, body);
     }
 
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index c136642dff2..69ba4840146 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -179,6 +179,29 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             }
                         }
                     }
+                    sym::write_via_move => {
+                        let target = target.unwrap();
+                        let Ok([ptr, val]) = <[_; 2]>::try_from(std::mem::take(args)) else {
+                            span_bug!(
+                                terminator.source_info.span,
+                                "Wrong number of arguments for write_via_move intrinsic",
+                            );
+                        };
+                        let derefed_place =
+                            if let Some(place) = ptr.place() && let Some(local) = place.as_local() {
+                                tcx.mk_place_deref(local.into())
+                            } else {
+                                span_bug!(terminator.source_info.span, "Only passing a local is supported");
+                            };
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                derefed_place,
+                                Rvalue::Use(val),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::discriminant_value => {
                         if let (Some(target), Some(arg)) = (*target, args[0].place()) {
                             let arg = tcx.mk_place_deref(arg);
@@ -192,6 +215,23 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             terminator.kind = TerminatorKind::Goto { target };
                         }
                     }
+                    sym::offset => {
+                        let target = target.unwrap();
+                        let Ok([ptr, delta]) = <[_; 2]>::try_from(std::mem::take(args)) else {
+                            span_bug!(
+                                terminator.source_info.span,
+                                "Wrong number of arguments for offset intrinsic",
+                            );
+                        };
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, delta))),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::option_payload_ptr => {
                         if let (Some(target), Some(arg)) = (*target, args[0].place()) {
                             let ty::RawPtr(ty::TypeAndMut { ty: dest_ty, .. }) =
@@ -221,7 +261,7 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                             terminator.kind = TerminatorKind::Goto { target };
                         }
                     }
-                    sym::transmute => {
+                    sym::transmute | sym::transmute_unchecked => {
                         let dst_ty = destination.ty(local_decls, tcx).ty;
                         let Ok([arg]) = <[_; 1]>::try_from(std::mem::take(args)) else {
                             span_bug!(
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 7dc5878e047..6e40dfa0d13 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -3,7 +3,7 @@
 
 use crate::MirPass;
 use rustc_hir::def_id::DefId;
-use rustc_index::vec::IndexSlice;
+use rustc_index::IndexSlice;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index ce05db5b762..59942dc76f9 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -46,7 +46,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let def_id = body.source.def_id();
-        let param_env = tcx.param_env(def_id);
+        let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
         let bbs = body.basic_blocks.as_mut();
         let mut should_cleanup = false;
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index b36c8a0bd53..b3b831bb4ab 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -3,7 +3,7 @@
 
 use crate::ssa::SsaLocals;
 use crate::MirPass;
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
new file mode 100644
index 00000000000..8be1c37572d
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -0,0 +1,23 @@
+//! This pass removes `PlaceMention` statement, which has no effect at codegen.
+
+use crate::MirPass;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+
+pub struct RemovePlaceMention;
+
+impl<'tcx> MirPass<'tcx> for RemovePlaceMention {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        !sess.opts.unstable_opts.mir_keep_place_mention
+    }
+
+    fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        trace!("Running RemovePlaceMention on {:?}", body.source);
+        for data in body.basic_blocks.as_mut_preserves_cfg() {
+            data.statements.retain(|statement| match statement.kind {
+                StatementKind::PlaceMention(..) | StatementKind::Nop => false,
+                _ => true,
+            })
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index abe6cb285f5..23442f8b97b 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -35,10 +35,22 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
     }
 
     #[inline]
+    fn visit_constant(&mut self, constant: &mut Constant<'tcx>, _: Location) {
+        // We have to use `try_normalize_erasing_regions` here, since it's
+        // possible that we visit impossible-to-satisfy where clauses here,
+        // see #91745
+        if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.literal) {
+            constant.literal = c;
+        }
+    }
+
+    #[inline]
     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
         // We have to use `try_normalize_erasing_regions` here, since it's
         // possible that we visit impossible-to-satisfy where clauses here,
         // see #91745
-        *ty = self.tcx.try_normalize_erasing_regions(self.param_env, *ty).unwrap_or(*ty);
+        if let Ok(t) = self.tcx.try_normalize_erasing_regions(self.param_env, *ty) {
+            *ty = t;
+        }
     }
 }
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index ef367faf6a7..2479856b727 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -303,8 +303,7 @@ fn find_determining_place<'tcx>(
                     | Rvalue::NullaryOp(_, _)
                     | Rvalue::ShallowInitBox(_, _)
                     | Rvalue::UnaryOp(_, Operand::Constant(_))
-                    | Rvalue::Cast(_, Operand::Constant(_), _)
-                    => return None,
+                    | Rvalue::Cast(_, Operand::Constant(_), _) => return None,
                 }
             }
 
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 2787fe2ce42..19d07fab0b9 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::InternalSubsts;
 use rustc_middle::ty::{self, EarlyBinder, GeneratorSubsts, Ty, TyCtxt};
 use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
 
-use rustc_index::vec::{Idx, IndexVec};
+use rustc_index::{Idx, IndexVec};
 
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
@@ -95,7 +95,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
             &add_moves_for_packed_drops::AddMovesForPackedDrops,
             &deref_separator::Derefer,
             &remove_noop_landing_pads::RemoveNoopLandingPads,
-            &simplify::SimplifyCfg::new("make_shim"),
+            &simplify::SimplifyCfg::MakeShim,
             &add_call_guards::CriticalCallEdges,
             &abort_unwinding_calls::AbortUnwindingCalls,
         ],
@@ -355,7 +355,7 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'t
 fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
     debug!("build_clone_shim(def_id={:?})", def_id);
 
-    let param_env = tcx.param_env(def_id);
+    let param_env = tcx.param_env_reveal_all_normalized(def_id);
 
     let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
     let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env);
@@ -836,7 +836,7 @@ fn build_call_shim<'tcx>(
 pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
     debug_assert!(tcx.is_constructor(ctor_id));
 
-    let param_env = tcx.param_env(ctor_id);
+    let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
 
     // Normalize the sig.
     let sig = tcx
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index c79e1cf0805..7e0cef025f7 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -29,20 +29,38 @@
 
 use crate::MirPass;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
-use rustc_index::vec::{Idx, IndexSlice, IndexVec};
+use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_middle::mir::coverage::*;
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use smallvec::SmallVec;
 
-pub struct SimplifyCfg {
-    label: String,
+pub enum SimplifyCfg {
+    Initial,
+    PromoteConsts,
+    RemoveFalseEdges,
+    EarlyOpt,
+    ElaborateDrops,
+    Final,
+    MakeShim,
+    AfterUninhabitedEnumBranching,
 }
 
 impl SimplifyCfg {
-    pub fn new(label: &str) -> Self {
-        SimplifyCfg { label: format!("SimplifyCfg-{}", label) }
+    pub fn name(&self) -> &'static str {
+        match self {
+            SimplifyCfg::Initial => "SimplifyCfg-initial",
+            SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts",
+            SimplifyCfg::RemoveFalseEdges => "SimplifyCfg-remove-false-edges",
+            SimplifyCfg::EarlyOpt => "SimplifyCfg-early-opt",
+            SimplifyCfg::ElaborateDrops => "SimplifyCfg-elaborate-drops",
+            SimplifyCfg::Final => "SimplifyCfg-final",
+            SimplifyCfg::MakeShim => "SimplifyCfg-make_shim",
+            SimplifyCfg::AfterUninhabitedEnumBranching => {
+                "SimplifyCfg-after-uninhabited-enum-branching"
+            }
+        }
     }
 }
 
@@ -57,11 +75,11 @@ pub fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 
 impl<'tcx> MirPass<'tcx> for SimplifyCfg {
     fn name(&self) -> &str {
-        &self.label
+        &self.name()
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body.source);
+        debug!("SimplifyCfg({:?}) - simplifying {:?}", self.name(), body.source);
         simplify_cfg(tcx, body);
     }
 }
@@ -260,6 +278,18 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
     }
 }
 
+pub fn combine_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
+    if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind {
+        let otherwise = targets.otherwise();
+        if targets.iter().any(|t| t.1 == otherwise) {
+            *targets = SwitchTargets::new(
+                targets.iter().filter(|t| t.1 != otherwise),
+                targets.otherwise(),
+            );
+        }
+    }
+}
+
 pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
     struct OptApplier<'tcx> {
         tcx: TyCtxt<'tcx>,
@@ -280,6 +310,8 @@ pub fn remove_duplicate_unreachable_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut B
                 }
             }
 
+            combine_duplicate_switch_targets(terminator);
+
             self.super_terminator(terminator, location);
         }
     }
@@ -423,19 +455,17 @@ fn save_unreachable_coverage(
     ));
 }
 
-pub struct SimplifyLocals {
-    label: String,
-}
-
-impl SimplifyLocals {
-    pub fn new(label: &str) -> SimplifyLocals {
-        SimplifyLocals { label: format!("SimplifyLocals-{}", label) }
-    }
+pub enum SimplifyLocals {
+    BeforeConstProp,
+    Final,
 }
 
 impl<'tcx> MirPass<'tcx> for SimplifyLocals {
-    fn name(&self) -> &str {
-        &self.label
+    fn name(&self) -> &'static str {
+        match &self {
+            SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop",
+            SimplifyLocals::Final => "SimplifyLocals-final",
+        }
     }
 
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 8164b305278..1ff48816986 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -2,24 +2,21 @@ use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
-/// A pass that replaces a branch with a goto when its condition is known.
-pub struct SimplifyConstCondition {
-    label: String,
-}
-
-impl SimplifyConstCondition {
-    pub fn new(label: &str) -> Self {
-        SimplifyConstCondition { label: format!("SimplifyConstCondition-{}", label) }
-    }
+pub enum SimplifyConstCondition {
+    AfterConstProp,
+    Final,
 }
-
+/// A pass that replaces a branch with a goto when its condition is known.
 impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
-    fn name(&self) -> &str {
-        &self.label
+    fn name(&self) -> &'static str {
+        match self {
+            SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop",
+            SimplifyConstCondition::Final => "SimplifyConstCondition-final",
+        }
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-        let param_env = tcx.param_env(body.source.def_id());
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         for block in body.basic_blocks_mut() {
             let terminator = block.terminator_mut();
             terminator.kind = match terminator.kind {
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index dcad1518eb6..113ca2fc5ad 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -37,7 +37,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
         let opts = helper.find_optimizations();
         let mut storage_deads_to_insert = vec![];
         let mut storage_deads_to_remove: Vec<(usize, BasicBlock)> = vec![];
-        let param_env = tcx.param_env(body.source.def_id());
+        let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         for opt in opts {
             trace!("SUCCESS: Applying {:?}", opt);
             // replace terminator with a switchInt that switches on the integer directly
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index c798bd05345..2d77291293d 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -1,6 +1,6 @@
 use crate::MirPass;
 use rustc_index::bit_set::{BitSet, GrowableBitSet};
-use rustc_index::vec::IndexVec;
+use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index be026402dd5..ec8d42c1652 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -1,7 +1,7 @@
 use either::Either;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
-use rustc_index::vec::{IndexSlice, IndexVec};
+use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
@@ -21,7 +21,7 @@ pub struct SsaLocals {
 
 /// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
 /// actually compute dominators, we can just compare block indices because bb0 is always the first
-/// block, and in any body all other blocks are always always dominated by bb0.
+/// block, and in any body all other blocks are always dominated by bb0.
 struct SmallDominators {
     inner: Option<Dominators<BasicBlock>>,
 }
diff --git a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
index be0aa0fc4c1..5389b9f52eb 100644
--- a/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
@@ -109,7 +109,9 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
                 continue;
             };
 
-            let layout = tcx.layout_of(tcx.param_env(body.source.def_id()).and(discriminant_ty));
+            let layout = tcx.layout_of(
+                tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
+            );
 
             let allowed_variants = if let Ok(layout) = layout {
                 variant_discriminants(&layout, discriminant_ty, tcx)