about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-09-20 01:38:26 +0000
committerbors <bors@rust-lang.org>2020-09-20 01:38:26 +0000
commit255a4c58f5863ed41c2e68792799125c6c676575 (patch)
tree07f3b9a5dccecda14b0b7f6e6579be0d615c5f73
parentf68e08933d8f519a9655934fedebbc509661b219 (diff)
parent2f9271b14c9ec0e5ed72ec91c2e24e850c580f83 (diff)
downloadrust-255a4c58f5863ed41c2e68792799125c6c676575.tar.gz
rust-255a4c58f5863ed41c2e68792799125c6c676575.zip
Auto merge of #72632 - jonas-schievink:dest-prop, r=oli-obk
Implement a generic Destination Propagation optimization on MIR

This takes the work that was originally started by `@eddyb` in https://github.com/rust-lang/rust/pull/47954, and then explored by me in https://github.com/rust-lang/rust/pull/71003, and implements it in a general (ie. not limited to acyclic CFGs) and dataflow-driven way (so that no additional infrastructure in rustc is needed).

The pass is configured to run at `mir-opt-level=2` and higher only. To enable it by default, some followup work on it is still needed:
* Performance needs to be evaluated. I did some light optimization work and tested against `tuple-stress`, which caused trouble in my last attempt, but didn't go much in depth here.
  * We can also enable the pass only at `opt-level=2` and higher, if it is too slow to run in debug mode, but fine when optimizations run anyways.
* Debuginfo needs to be fixed after locals are merged. I did not look into what is required for this.
* Live ranges of locals (aka `StorageLive` and `StorageDead`) are currently deleted. We either need to decide that this is fine, or if not, merge the variable's live ranges (or remove these statements entirely – https://github.com/rust-lang/rust/issues/68622).

Some benchmarks of the pass were done in https://github.com/rust-lang/rust/pull/72635.
-rw-r--r--compiler/rustc_mir/src/dataflow/impls/mod.rs2
-rw-r--r--compiler/rustc_mir/src/lib.rs1
-rw-r--r--compiler/rustc_mir/src/transform/dest_prop.rs1057
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs2
-rw-r--r--compiler/rustc_mir/src/transform/nrvo.rs6
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir28
-rw-r--r--src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir32
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir26
-rw-r--r--src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir28
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir4
-rw-r--r--src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir4
-rw-r--r--src/test/mir-opt/copy_propagation.test.CopyPropagation.diff15
-rw-r--r--src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff10
-rw-r--r--src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff8
-rw-r--r--src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff8
-rw-r--r--src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff73
-rw-r--r--src/test/mir-opt/dest-prop/branch.rs21
-rw-r--r--src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff76
-rw-r--r--src/test/mir-opt/dest-prop/cycle.rs15
-rw-r--r--src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff45
-rw-r--r--src/test/mir-opt/dest-prop/simple.rs14
-rw-r--r--src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff46
-rw-r--r--src/test/mir-opt/dest-prop/union.rs16
-rw-r--r--src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir24
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff207
-rw-r--r--src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff207
-rw-r--r--src/test/mir-opt/nrvo-simple.rs2
-rw-r--r--src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff55
-rw-r--r--src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff72
-rw-r--r--src/test/mir-opt/simplify_try.rs1
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff72
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff102
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir56
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir16
-rw-r--r--src/test/ui/dest-prop/skeptic-miscompile.rs24
35 files changed, 1919 insertions, 456 deletions
diff --git a/compiler/rustc_mir/src/dataflow/impls/mod.rs b/compiler/rustc_mir/src/dataflow/impls/mod.rs
index c42d5867856..1769feaf7a5 100644
--- a/compiler/rustc_mir/src/dataflow/impls/mod.rs
+++ b/compiler/rustc_mir/src/dataflow/impls/mod.rs
@@ -204,7 +204,7 @@ impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
 
 /// `EverInitializedPlaces` tracks all places that might have ever been
 /// initialized upon reaching a particular point in the control flow
-/// for a function, without an intervening `Storage Dead`.
+/// for a function, without an intervening `StorageDead`.
 ///
 /// This dataflow is used to determine if an immutable local variable may
 /// be assigned to.
diff --git a/compiler/rustc_mir/src/lib.rs b/compiler/rustc_mir/src/lib.rs
index 42717f27384..251037792c9 100644
--- a/compiler/rustc_mir/src/lib.rs
+++ b/compiler/rustc_mir/src/lib.rs
@@ -6,6 +6,7 @@ Rust MIR: a lowered representation of Rust.
 
 #![feature(nll)]
 #![feature(in_band_lifetimes)]
+#![feature(bindings_after_at)]
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs
new file mode 100644
index 00000000000..46cbced2d54
--- /dev/null
+++ b/compiler/rustc_mir/src/transform/dest_prop.rs
@@ -0,0 +1,1057 @@
+//! Propagates assignment destinations backwards in the CFG to eliminate redundant assignments.
+//!
+//! # Motivation
+//!
+//! MIR building can insert a lot of redundant copies, and Rust code in general often tends to move
+//! values around a lot. The result is a lot of assignments of the form `dest = {move} src;` in MIR.
+//! MIR building for constants in particular tends to create additional locals that are only used
+//! inside a single block to shuffle a value around unnecessarily.
+//!
+//! LLVM by itself is not good enough at eliminating these redundant copies (eg. see
+//! https://github.com/rust-lang/rust/issues/32966), so this leaves some performance on the table
+//! that we can regain by implementing an optimization for removing these assign statements in rustc
+//! itself. When this optimization runs fast enough, it can also speed up the constant evaluation
+//! and code generation phases of rustc due to the reduced number of statements and locals.
+//!
+//! # The Optimization
+//!
+//! Conceptually, this optimization is "destination propagation". It is similar to the Named Return
+//! Value Optimization, or NRVO, known from the C++ world, except that it isn't limited to return
+//! values or the return place `_0`. On a very high level, independent of the actual implementation
+//! details, it does the following:
+//!
+//! 1) Identify `dest = src;` statements that can be soundly eliminated.
+//! 2) Replace all mentions of `src` with `dest` ("unifying" them and propagating the destination
+//!    backwards).
+//! 3) Delete the `dest = src;` statement (by making it a `nop`).
+//!
+//! Step 1) is by far the hardest, so it is explained in more detail below.
+//!
+//! ## Soundness
+//!
+//! Given an `Assign` statement `dest = src;`, where `dest` is a `Place` and `src` is an `Rvalue`,
+//! there are a few requirements that must hold for the optimization to be sound:
+//!
+//! * `dest` must not contain any *indirection* through a pointer. It must access part of the base
+//!   local. Otherwise it might point to arbitrary memory that is hard to track.
+//!
+//!   It must also not contain any indexing projections, since those take an arbitrary `Local` as
+//!   the index, and that local might only be initialized shortly before `dest` is used.
+//!
+//!   Subtle case: If `dest` is a, or projects through a union, then we have to make sure that there
+//!   remains an assignment to it, since that sets the "active field" of the union. But if `src` is
+//!   a ZST, it might not be initialized, so there might not be any use of it before the assignment,
+//!   and performing the optimization would simply delete the assignment, leaving `dest`
+//!   uninitialized.
+//!
+//! * `src` must be a bare `Local` without any indirections or field projections (FIXME: Is this a
+//!   fundamental restriction or just current impl state?). It can be copied or moved by the
+//!   assignment.
+//!
+//! * The `dest` and `src` locals must never be [*live*][liveness] at the same time. If they are, it
+//!   means that they both hold a (potentially different) value that is needed by a future use of
+//!   the locals. Unifying them would overwrite one of the values.
+//!
+//!   Note that computing liveness of locals that have had their address taken is more difficult:
+//!   Short of doing full escape analysis on the address/pointer/reference, the pass would need to
+//!   assume that any operation that can potentially involve opaque user code (such as function
+//!   calls, destructors, and inline assembly) may access any local that had its address taken
+//!   before that point.
+//!
+//! Here, the first two conditions are simple structural requirements on the `Assign` statements
+//! that can be trivially checked. The liveness requirement however is more difficult and costly to
+//! check.
+//!
+//! ## Previous Work
+//!
+//! A [previous attempt] at implementing an optimization like this turned out to be a significant
+//! regression in compiler performance. Fixing the regressions introduced a lot of undesirable
+//! complexity to the implementation.
+//!
+//! A [subsequent approach] tried to avoid the costly computation by limiting itself to acyclic
+//! CFGs, but still turned out to be far too costly to run due to suboptimal performance within
+//! individual basic blocks, requiring a walk across the entire block for every assignment found
+//! within the block. For the `tuple-stress` benchmark, which has 458745 statements in a single
+//! block, this proved to be far too costly.
+//!
+//! Since the first attempt at this, the compiler has improved dramatically, and new analysis
+//! frameworks have been added that should make this approach viable without requiring a limited
+//! approach that only works for some classes of CFGs:
+//! - rustc now has a powerful dataflow analysis framework that can handle forwards and backwards
+//!   analyses efficiently.
+//! - Layout optimizations for generators have been added to improve code generation for
+//!   async/await, which are very similar in spirit to what this optimization does. Both walk the
+//!   MIR and record conflicting uses of locals in a `BitMatrix`.
+//!
+//! Also, rustc now has a simple NRVO pass (see `nrvo.rs`), which handles a subset of the cases that
+//! this destination propagation pass handles, proving that similar optimizations can be performed
+//! on MIR.
+//!
+//! ## Pre/Post Optimization
+//!
+//! It is recommended to run `SimplifyCfg` and then `SimplifyLocals` some time after this pass, as
+//! it replaces the eliminated assign statements with `nop`s and leaves unused locals behind.
+//!
+//! [liveness]: https://en.wikipedia.org/wiki/Live_variable_analysis
+//! [previous attempt]: https://github.com/rust-lang/rust/pull/47954
+//! [subsequent approach]: https://github.com/rust-lang/rust/pull/71003
+
+use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals};
+use crate::dataflow::Analysis;
+use crate::{
+    transform::{MirPass, MirSource},
+    util::{dump_mir, PassWhere},
+};
+use itertools::Itertools;
+use rustc_data_structures::unify::{InPlaceUnificationTable, UnifyKey};
+use rustc_index::{
+    bit_set::{BitMatrix, BitSet},
+    vec::IndexVec,
+};
+use rustc_middle::mir::tcx::PlaceTy;
+use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
+use rustc_middle::mir::{
+    traversal, Body, InlineAsmOperand, Local, LocalKind, Location, Operand, Place, PlaceElem,
+    Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
+};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+// Empirical measurements have resulted in some observations:
+// - Running on a body with a single block and 500 locals takes barely any time
+// - Running on a body with ~400 blocks and ~300 relevant locals takes "too long"
+// ...so we just limit both to somewhat reasonable-ish looking values.
+const MAX_LOCALS: usize = 500;
+const MAX_BLOCKS: usize = 250;
+
+pub struct DestinationPropagation;
+
+impl<'tcx> MirPass<'tcx> for DestinationPropagation {
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+        // Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove
+        // storage statements at the moment).
+        if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
+            return;
+        }
+
+        let candidates = find_candidates(tcx, body);
+        if candidates.is_empty() {
+            debug!("{:?}: no dest prop candidates, done", source.def_id());
+            return;
+        }
+
+        // Collect all locals we care about. We only compute conflicts for these to save time.
+        let mut relevant_locals = BitSet::new_empty(body.local_decls.len());
+        for CandidateAssignment { dest, src, loc: _ } in &candidates {
+            relevant_locals.insert(dest.local);
+            relevant_locals.insert(*src);
+        }
+
+        // This pass unfortunately has `O(l² * s)` performance, where `l` is the number of locals
+        // and `s` is the number of statements and terminators in the function.
+        // To prevent blowing up compile times too much, we bail out when there are too many locals.
+        let relevant = relevant_locals.count();
+        debug!(
+            "{:?}: {} locals ({} relevant), {} blocks",
+            source.def_id(),
+            body.local_decls.len(),
+            relevant,
+            body.basic_blocks().len()
+        );
+        if relevant > MAX_LOCALS {
+            warn!(
+                "too many candidate locals in {:?} ({}, max is {}), not optimizing",
+                source.def_id(),
+                relevant,
+                MAX_LOCALS
+            );
+            return;
+        }
+        if body.basic_blocks().len() > MAX_BLOCKS {
+            warn!(
+                "too many blocks in {:?} ({}, max is {}), not optimizing",
+                source.def_id(),
+                body.basic_blocks().len(),
+                MAX_BLOCKS
+            );
+            return;
+        }
+
+        let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals);
+
+        let mut replacements = Replacements::new(body.local_decls.len());
+        for candidate @ CandidateAssignment { dest, src, loc } in candidates {
+            // Merge locals that don't conflict.
+            if !conflicts.can_unify(dest.local, src) {
+                debug!("at assignment {:?}, conflict {:?} vs. {:?}", loc, dest.local, src);
+                continue;
+            }
+
+            if replacements.for_src(candidate.src).is_some() {
+                debug!("src {:?} already has replacement", candidate.src);
+                continue;
+            }
+
+            if !tcx.consider_optimizing(|| {
+                format!("DestinationPropagation {:?} {:?}", source.def_id(), candidate)
+            }) {
+                break;
+            }
+
+            replacements.push(candidate);
+            conflicts.unify(candidate.src, candidate.dest.local);
+        }
+
+        replacements.flatten(tcx);
+
+        debug!("replacements {:?}", replacements.map);
+
+        Replacer { tcx, replacements, place_elem_cache: Vec::new() }.visit_body(body);
+
+        // FIXME fix debug info
+    }
+}
+
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+struct UnifyLocal(Local);
+
+impl From<Local> for UnifyLocal {
+    fn from(l: Local) -> Self {
+        Self(l)
+    }
+}
+
+impl UnifyKey for UnifyLocal {
+    type Value = ();
+    fn index(&self) -> u32 {
+        self.0.as_u32()
+    }
+    fn from_index(u: u32) -> Self {
+        Self(Local::from_u32(u))
+    }
+    fn tag() -> &'static str {
+        "UnifyLocal"
+    }
+}
+
+struct Replacements<'tcx> {
+    /// Maps locals to their replacement.
+    map: IndexVec<Local, Option<Place<'tcx>>>,
+
+    /// Whose locals' live ranges to kill.
+    kill: BitSet<Local>,
+}
+
+impl Replacements<'tcx> {
+    fn new(locals: usize) -> Self {
+        Self { map: IndexVec::from_elem_n(None, locals), kill: BitSet::new_empty(locals) }
+    }
+
+    fn push(&mut self, candidate: CandidateAssignment<'tcx>) {
+        trace!("Replacements::push({:?})", candidate);
+        let entry = &mut self.map[candidate.src];
+        assert!(entry.is_none());
+
+        *entry = Some(candidate.dest);
+        self.kill.insert(candidate.src);
+        self.kill.insert(candidate.dest.local);
+    }
+
+    /// Applies the stored replacements to all replacements, until no replacements would result in
+    /// locals that need further replacements when applied.
+    fn flatten(&mut self, tcx: TyCtxt<'tcx>) {
+        // Note: This assumes that there are no cycles in the replacements, which is enforced via
+        // `self.unified_locals`. Otherwise this can cause an infinite loop.
+
+        for local in self.map.indices() {
+            if let Some(replacement) = self.map[local] {
+                // Substitute the base local of `replacement` until fixpoint.
+                let mut base = replacement.local;
+                let mut reversed_projection_slices = Vec::with_capacity(1);
+                while let Some(replacement_for_replacement) = self.map[base] {
+                    base = replacement_for_replacement.local;
+                    reversed_projection_slices.push(replacement_for_replacement.projection);
+                }
+
+                let projection: Vec<_> = reversed_projection_slices
+                    .iter()
+                    .rev()
+                    .flat_map(|projs| projs.iter())
+                    .chain(replacement.projection.iter())
+                    .collect();
+                let projection = tcx.intern_place_elems(&projection);
+
+                // Replace with the final `Place`.
+                self.map[local] = Some(Place { local: base, projection });
+            }
+        }
+    }
+
+    fn for_src(&self, src: Local) -> Option<Place<'tcx>> {
+        self.map[src]
+    }
+}
+
+struct Replacer<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    replacements: Replacements<'tcx>,
+    place_elem_cache: Vec<PlaceElem<'tcx>>,
+}
+
+impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_local(&mut self, local: &mut Local, context: PlaceContext, location: Location) {
+        if context.is_use() && self.replacements.for_src(*local).is_some() {
+            bug!(
+                "use of local {:?} should have been replaced by visit_place; context={:?}, loc={:?}",
+                local,
+                context,
+                location,
+            );
+        }
+    }
+
+    fn process_projection_elem(
+        &mut self,
+        elem: PlaceElem<'tcx>,
+        _: Location,
+    ) -> Option<PlaceElem<'tcx>> {
+        match elem {
+            PlaceElem::Index(local) => {
+                if let Some(replacement) = self.replacements.for_src(local) {
+                    bug!(
+                        "cannot replace {:?} with {:?} in index projection {:?}",
+                        local,
+                        replacement,
+                        elem,
+                    );
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+
+    fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
+        if let Some(replacement) = self.replacements.for_src(place.local) {
+            // Rebase `place`s projections onto `replacement`'s.
+            self.place_elem_cache.clear();
+            self.place_elem_cache.extend(replacement.projection.iter().chain(place.projection));
+            let projection = self.tcx.intern_place_elems(&self.place_elem_cache);
+            let new_place = Place { local: replacement.local, projection };
+
+            debug!("Replacer: {:?} -> {:?}", place, new_place);
+            *place = new_place;
+        }
+
+        self.super_place(place, context, location);
+    }
+
+    fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
+        self.super_statement(statement, location);
+
+        match &statement.kind {
+            // FIXME: Don't delete storage statements, merge the live ranges instead
+            StatementKind::StorageDead(local) | StatementKind::StorageLive(local)
+                if self.replacements.kill.contains(*local) =>
+            {
+                statement.make_nop()
+            }
+
+            StatementKind::Assign(box (dest, rvalue)) => {
+                match rvalue {
+                    Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => {
+                        // These might've been turned into self-assignments by the replacement
+                        // (this includes the original statement we wanted to eliminate).
+                        if dest == place {
+                            debug!("{:?} turned into self-assignment, deleting", location);
+                            statement.make_nop();
+                        }
+                    }
+                    _ => {}
+                }
+            }
+
+            _ => {}
+        }
+    }
+}
+
+struct Conflicts<'a> {
+    relevant_locals: &'a BitSet<Local>,
+
+    /// The conflict matrix. It is always symmetric and the adjacency matrix of the corresponding
+    /// conflict graph.
+    matrix: BitMatrix<Local, Local>,
+
+    /// Preallocated `BitSet` used by `unify`.
+    unify_cache: BitSet<Local>,
+
+    /// Tracks locals that have been merged together to prevent cycles and propagate conflicts.
+    unified_locals: InPlaceUnificationTable<UnifyLocal>,
+}
+
+impl Conflicts<'a> {
+    fn build<'tcx>(
+        tcx: TyCtxt<'tcx>,
+        body: &'_ Body<'tcx>,
+        source: MirSource<'tcx>,
+        relevant_locals: &'a BitSet<Local>,
+    ) -> Self {
+        // We don't have to look out for locals that have their address taken, since
+        // `find_candidates` already takes care of that.
+
+        let conflicts = BitMatrix::from_row_n(
+            &BitSet::new_empty(body.local_decls.len()),
+            body.local_decls.len(),
+        );
+
+        let def_id = source.def_id();
+        let mut init = MaybeInitializedLocals
+            .into_engine(tcx, body, def_id)
+            .iterate_to_fixpoint()
+            .into_results_cursor(body);
+        let mut live = MaybeLiveLocals
+            .into_engine(tcx, body, def_id)
+            .iterate_to_fixpoint()
+            .into_results_cursor(body);
+
+        let mut reachable = None;
+        dump_mir(
+            tcx,
+            None,
+            "DestinationPropagation-dataflow",
+            &"",
+            source,
+            body,
+            |pass_where, w| {
+                let reachable =
+                    reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body));
+
+                match pass_where {
+                    PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => {
+                        init.seek_before_primary_effect(loc);
+                        live.seek_after_primary_effect(loc);
+
+                        writeln!(w, "        // init: {:?}", init.get())?;
+                        writeln!(w, "        // live: {:?}", live.get())?;
+                    }
+                    PassWhere::AfterTerminator(bb) if reachable.contains(bb) => {
+                        let loc = body.terminator_loc(bb);
+                        init.seek_after_primary_effect(loc);
+                        live.seek_before_primary_effect(loc);
+
+                        writeln!(w, "        // init: {:?}", init.get())?;
+                        writeln!(w, "        // live: {:?}", live.get())?;
+                    }
+
+                    PassWhere::BeforeBlock(bb) if reachable.contains(bb) => {
+                        init.seek_to_block_start(bb);
+                        live.seek_to_block_start(bb);
+
+                        writeln!(w, "    // init: {:?}", init.get())?;
+                        writeln!(w, "    // live: {:?}", live.get())?;
+                    }
+
+                    PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {}
+
+                    PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => {
+                        writeln!(w, "        // init: <unreachable>")?;
+                        writeln!(w, "        // live: <unreachable>")?;
+                    }
+
+                    PassWhere::BeforeBlock(_) => {
+                        writeln!(w, "    // init: <unreachable>")?;
+                        writeln!(w, "    // live: <unreachable>")?;
+                    }
+                }
+
+                Ok(())
+            },
+        );
+
+        let mut this = Self {
+            relevant_locals,
+            matrix: conflicts,
+            unify_cache: BitSet::new_empty(body.local_decls.len()),
+            unified_locals: {
+                let mut table = InPlaceUnificationTable::new();
+                // Pre-fill table with all locals (this creates N nodes / "connected" components,
+                // "graph"-ically speaking).
+                for local in 0..body.local_decls.len() {
+                    assert_eq!(table.new_key(()), UnifyLocal(Local::from_usize(local)));
+                }
+                table
+            },
+        };
+
+        let mut live_and_init_locals = Vec::new();
+
+        // Visit only reachable basic blocks. The exact order is not important.
+        for (block, data) in traversal::preorder(body) {
+            // We need to observe the dataflow state *before* all possible locations (statement or
+            // terminator) in each basic block, and then observe the state *after* the terminator
+            // effect is applied. As long as neither `init` nor `borrowed` has a "before" effect,
+            // we will observe all possible dataflow states.
+
+            // Since liveness is a backwards analysis, we need to walk the results backwards. To do
+            // that, we first collect in the `MaybeInitializedLocals` results in a forwards
+            // traversal.
+
+            live_and_init_locals.resize_with(data.statements.len() + 1, || {
+                BitSet::new_empty(body.local_decls.len())
+            });
+
+            // First, go forwards for `MaybeInitializedLocals` and apply intra-statement/terminator
+            // conflicts.
+            for (i, statement) in data.statements.iter().enumerate() {
+                this.record_statement_conflicts(statement);
+
+                let loc = Location { block, statement_index: i };
+                init.seek_before_primary_effect(loc);
+
+                live_and_init_locals[i].clone_from(init.get());
+            }
+
+            this.record_terminator_conflicts(data.terminator());
+            let term_loc = Location { block, statement_index: data.statements.len() };
+            init.seek_before_primary_effect(term_loc);
+            live_and_init_locals[term_loc.statement_index].clone_from(init.get());
+
+            // Now, go backwards and union with the liveness results.
+            for statement_index in (0..=data.statements.len()).rev() {
+                let loc = Location { block, statement_index };
+                live.seek_after_primary_effect(loc);
+
+                live_and_init_locals[statement_index].intersect(live.get());
+
+                trace!("record conflicts at {:?}", loc);
+
+                this.record_dataflow_conflicts(&mut live_and_init_locals[statement_index]);
+            }
+
+            init.seek_to_block_end(block);
+            live.seek_to_block_end(block);
+            let mut conflicts = init.get().clone();
+            conflicts.intersect(live.get());
+            trace!("record conflicts at end of {:?}", block);
+
+            this.record_dataflow_conflicts(&mut conflicts);
+        }
+
+        this
+    }
+
+    fn record_dataflow_conflicts(&mut self, new_conflicts: &mut BitSet<Local>) {
+        // Remove all locals that are not candidates.
+        new_conflicts.intersect(self.relevant_locals);
+
+        for local in new_conflicts.iter() {
+            self.matrix.union_row_with(&new_conflicts, local);
+        }
+    }
+
+    fn record_local_conflict(&mut self, a: Local, b: Local, why: &str) {
+        trace!("conflict {:?} <-> {:?} due to {}", a, b, why);
+        self.matrix.insert(a, b);
+        self.matrix.insert(b, a);
+    }
+
+    /// Records locals that must not overlap during the evaluation of `stmt`. These locals conflict
+    /// and must not be merged.
+    fn record_statement_conflicts(&mut self, stmt: &Statement<'_>) {
+        match &stmt.kind {
+            // While the left and right sides of an assignment must not overlap, we do not mark
+            // conflicts here as that would make this optimization useless. When we optimize, we
+            // eliminate the resulting self-assignments automatically.
+            StatementKind::Assign(_) => {}
+
+            StatementKind::LlvmInlineAsm(asm) => {
+                // Inputs and outputs must not overlap.
+                for (_, input) in &*asm.inputs {
+                    if let Some(in_place) = input.place() {
+                        if !in_place.is_indirect() {
+                            for out_place in &*asm.outputs {
+                                if !out_place.is_indirect() && !in_place.is_indirect() {
+                                    self.record_local_conflict(
+                                        in_place.local,
+                                        out_place.local,
+                                        "aliasing llvm_asm! operands",
+                                    );
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            StatementKind::SetDiscriminant { .. }
+            | StatementKind::StorageLive(..)
+            | StatementKind::StorageDead(..)
+            | StatementKind::Retag(..)
+            | StatementKind::FakeRead(..)
+            | StatementKind::AscribeUserType(..)
+            | StatementKind::Coverage(..)
+            | StatementKind::Nop => {}
+        }
+    }
+
+    fn record_terminator_conflicts(&mut self, term: &Terminator<'_>) {
+        match &term.kind {
+            TerminatorKind::DropAndReplace {
+                place: dropped_place,
+                value,
+                target: _,
+                unwind: _,
+            } => {
+                if let Some(place) = value.place() {
+                    if !place.is_indirect() && !dropped_place.is_indirect() {
+                        self.record_local_conflict(
+                            place.local,
+                            dropped_place.local,
+                            "DropAndReplace operand overlap",
+                        );
+                    }
+                }
+            }
+            TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
+                if let Some(place) = value.place() {
+                    if !place.is_indirect() && !resume_arg.is_indirect() {
+                        self.record_local_conflict(
+                            place.local,
+                            resume_arg.local,
+                            "Yield operand overlap",
+                        );
+                    }
+                }
+            }
+            TerminatorKind::Call {
+                func,
+                args,
+                destination: Some((dest_place, _)),
+                cleanup: _,
+                from_hir_call: _,
+                fn_span: _,
+            } => {
+                // No arguments may overlap with the destination.
+                for arg in args.iter().chain(Some(func)) {
+                    if let Some(place) = arg.place() {
+                        if !place.is_indirect() && !dest_place.is_indirect() {
+                            self.record_local_conflict(
+                                dest_place.local,
+                                place.local,
+                                "call dest/arg overlap",
+                            );
+                        }
+                    }
+                }
+            }
+            TerminatorKind::InlineAsm {
+                template: _,
+                operands,
+                options: _,
+                line_spans: _,
+                destination: _,
+            } => {
+                // The intended semantics here aren't documented, we just assume that nothing that
+                // could be written to by the assembly may overlap with any other operands.
+                for op in operands {
+                    match op {
+                        InlineAsmOperand::Out { reg: _, late: _, place: Some(dest_place) }
+                        | InlineAsmOperand::InOut {
+                            reg: _,
+                            late: _,
+                            in_value: _,
+                            out_place: Some(dest_place),
+                        } => {
+                            // For output place `place`, add all places accessed by the inline asm.
+                            for op in operands {
+                                match op {
+                                    InlineAsmOperand::In { reg: _, value } => {
+                                        if let Some(p) = value.place() {
+                                            if !p.is_indirect() && !dest_place.is_indirect() {
+                                                self.record_local_conflict(
+                                                    p.local,
+                                                    dest_place.local,
+                                                    "asm! operand overlap",
+                                                );
+                                            }
+                                        }
+                                    }
+                                    InlineAsmOperand::Out {
+                                        reg: _,
+                                        late: _,
+                                        place: Some(place),
+                                    } => {
+                                        if !place.is_indirect() && !dest_place.is_indirect() {
+                                            self.record_local_conflict(
+                                                place.local,
+                                                dest_place.local,
+                                                "asm! operand overlap",
+                                            );
+                                        }
+                                    }
+                                    InlineAsmOperand::InOut {
+                                        reg: _,
+                                        late: _,
+                                        in_value,
+                                        out_place,
+                                    } => {
+                                        if let Some(place) = in_value.place() {
+                                            if !place.is_indirect() && !dest_place.is_indirect() {
+                                                self.record_local_conflict(
+                                                    place.local,
+                                                    dest_place.local,
+                                                    "asm! operand overlap",
+                                                );
+                                            }
+                                        }
+
+                                        if let Some(place) = out_place {
+                                            if !place.is_indirect() && !dest_place.is_indirect() {
+                                                self.record_local_conflict(
+                                                    place.local,
+                                                    dest_place.local,
+                                                    "asm! operand overlap",
+                                                );
+                                            }
+                                        }
+                                    }
+                                    InlineAsmOperand::Out { reg: _, late: _, place: None }
+                                    | InlineAsmOperand::Const { value: _ }
+                                    | InlineAsmOperand::SymFn { value: _ }
+                                    | InlineAsmOperand::SymStatic { def_id: _ } => {}
+                                }
+                            }
+                        }
+                        InlineAsmOperand::Const { value } => {
+                            assert!(value.place().is_none());
+                        }
+                        InlineAsmOperand::InOut {
+                            reg: _,
+                            late: _,
+                            in_value: _,
+                            out_place: None,
+                        }
+                        | InlineAsmOperand::In { reg: _, value: _ }
+                        | InlineAsmOperand::Out { reg: _, late: _, place: None }
+                        | InlineAsmOperand::SymFn { value: _ }
+                        | InlineAsmOperand::SymStatic { def_id: _ } => {}
+                    }
+                }
+            }
+
+            TerminatorKind::Goto { .. }
+            | TerminatorKind::Call { destination: None, .. }
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Abort
+            | TerminatorKind::Return
+            | TerminatorKind::Unreachable
+            | TerminatorKind::Drop { .. }
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::FalseEdge { .. }
+            | TerminatorKind::FalseUnwind { .. } => {}
+        }
+    }
+
+    /// Checks whether `a` and `b` may be merged. Returns `false` if there's a conflict.
+    fn can_unify(&mut self, a: Local, b: Local) -> bool {
+        // After some locals have been unified, their conflicts are only tracked in the root key,
+        // so look that up.
+        let a = self.unified_locals.find(a).0;
+        let b = self.unified_locals.find(b).0;
+
+        if a == b {
+            // Already merged (part of the same connected component).
+            return false;
+        }
+
+        if self.matrix.contains(a, b) {
+            // Conflict (derived via dataflow, intra-statement conflicts, or inherited from another
+            // local during unification).
+            return false;
+        }
+
+        true
+    }
+
+    /// Merges the conflicts of `a` and `b`, so that each one inherits all conflicts of the other.
+    ///
+    /// `can_unify` must have returned `true` for the same locals, or this may panic or lead to
+    /// miscompiles.
+    ///
+    /// This is called when the pass makes the decision to unify `a` and `b` (or parts of `a` and
+    /// `b`) and is needed to ensure that future unification decisions take potentially newly
+    /// introduced conflicts into account.
+    ///
+    /// For an example, assume we have locals `_0`, `_1`, `_2`, and `_3`. There are these conflicts:
+    ///
+    /// * `_0` <-> `_1`
+    /// * `_1` <-> `_2`
+    /// * `_3` <-> `_0`
+    ///
+    /// We then decide to merge `_2` with `_3` since they don't conflict. Then we decide to merge
+    /// `_2` with `_0`, which also doesn't have a conflict in the above list. However `_2` is now
+    /// `_3`, which does conflict with `_0`.
+    fn unify(&mut self, a: Local, b: Local) {
+        trace!("unify({:?}, {:?})", a, b);
+
+        // Get the root local of the connected components. The root local stores the conflicts of
+        // all locals in the connected component (and *is stored* as the conflicting local of other
+        // locals).
+        let a = self.unified_locals.find(a).0;
+        let b = self.unified_locals.find(b).0;
+        assert_ne!(a, b);
+
+        trace!("roots: a={:?}, b={:?}", a, b);
+        trace!("{:?} conflicts: {:?}", a, self.matrix.iter(a).format(", "));
+        trace!("{:?} conflicts: {:?}", b, self.matrix.iter(b).format(", "));
+
+        self.unified_locals.union(a, b);
+
+        let root = self.unified_locals.find(a).0;
+        assert!(root == a || root == b);
+
+        // Make all locals that conflict with `a` also conflict with `b`, and vice versa.
+        self.unify_cache.clear();
+        for conflicts_with_a in self.matrix.iter(a) {
+            self.unify_cache.insert(conflicts_with_a);
+        }
+        for conflicts_with_b in self.matrix.iter(b) {
+            self.unify_cache.insert(conflicts_with_b);
+        }
+        for conflicts_with_a_or_b in self.unify_cache.iter() {
+            // Set both `a` and `b` for this local's row.
+            self.matrix.insert(conflicts_with_a_or_b, a);
+            self.matrix.insert(conflicts_with_a_or_b, b);
+        }
+
+        // Write the locals `a` conflicts with to `b`'s row.
+        self.matrix.union_rows(a, b);
+        // Write the locals `b` conflicts with to `a`'s row.
+        self.matrix.union_rows(b, a);
+    }
+}
+
+/// A `dest = {move} src;` statement at `loc`.
+///
+/// We want to consider merging `dest` and `src` due to this assignment.
+#[derive(Debug, Copy, Clone)]
+struct CandidateAssignment<'tcx> {
+    /// Does not contain indirection or indexing (so the only local it contains is the place base).
+    dest: Place<'tcx>,
+    src: Local,
+    loc: Location,
+}
+
+/// Scans the MIR for assignments between locals that we might want to consider merging.
+///
+/// This will filter out assignments that do not match the right form (as described in the top-level
+/// comment) and also throw out assignments that involve a local that has its address taken or is
+/// otherwise ineligible (eg. locals used as array indices are ignored because we cannot propagate
+/// arbitrary places into array indices).
+fn find_candidates<'a, 'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+) -> Vec<CandidateAssignment<'tcx>> {
+    let mut visitor = FindAssignments {
+        tcx,
+        body,
+        candidates: Vec::new(),
+        ever_borrowed_locals: ever_borrowed_locals(body),
+        locals_used_as_array_index: locals_used_as_array_index(body),
+    };
+    visitor.visit_body(body);
+    visitor.candidates
+}
+
+struct FindAssignments<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+    candidates: Vec<CandidateAssignment<'tcx>>,
+    ever_borrowed_locals: BitSet<Local>,
+    locals_used_as_array_index: BitSet<Local>,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for FindAssignments<'a, 'tcx> {
+    fn visit_statement(&mut self, statement: &Statement<'tcx>, location: Location) {
+        if let StatementKind::Assign(box (
+            dest,
+            Rvalue::Use(Operand::Copy(src) | Operand::Move(src)),
+        )) = &statement.kind
+        {
+            // `dest` must not have pointer indirection.
+            if dest.is_indirect() {
+                return;
+            }
+
+            // `src` must be a plain local.
+            if !src.projection.is_empty() {
+                return;
+            }
+
+            // Since we want to replace `src` with `dest`, `src` must not be required.
+            if is_local_required(src.local, self.body) {
+                return;
+            }
+
+            // Can't optimize if both locals ever have their address taken (can introduce
+            // aliasing).
+            // FIXME: This can be smarter and take `StorageDead` into account (which
+            // invalidates borrows).
+            if self.ever_borrowed_locals.contains(dest.local)
+                && self.ever_borrowed_locals.contains(src.local)
+            {
+                return;
+            }
+
+            assert_ne!(dest.local, src.local, "self-assignments are UB");
+
+            // We can't replace locals occurring in `PlaceElem::Index` for now.
+            if self.locals_used_as_array_index.contains(src.local) {
+                return;
+            }
+
+            // Handle the "subtle case" described above by rejecting any `dest` that is or
+            // projects through a union.
+            let is_union = |ty: Ty<'_>| {
+                if let ty::Adt(def, _) = ty.kind() {
+                    if def.is_union() {
+                        return true;
+                    }
+                }
+
+                false
+            };
+            let mut place_ty = PlaceTy::from_ty(self.body.local_decls[dest.local].ty);
+            if is_union(place_ty.ty) {
+                return;
+            }
+            for elem in dest.projection {
+                if let PlaceElem::Index(_) = elem {
+                    // `dest` contains an indexing projection.
+                    return;
+                }
+
+                place_ty = place_ty.projection_ty(self.tcx, elem);
+                if is_union(place_ty.ty) {
+                    return;
+                }
+            }
+
+            self.candidates.push(CandidateAssignment {
+                dest: *dest,
+                src: src.local,
+                loc: location,
+            });
+        }
+    }
+}
+
+/// Some locals are part of the function's interface and can not be removed.
+///
+/// Note that these locals *can* still be merged with non-required locals by removing that other
+/// local.
+fn is_local_required(local: Local, body: &Body<'_>) -> bool {
+    match body.local_kind(local) {
+        LocalKind::Arg | LocalKind::ReturnPointer => true,
+        LocalKind::Var | LocalKind::Temp => false,
+    }
+}
+
+/// Walks MIR to find all locals that have their address taken anywhere.
+fn ever_borrowed_locals(body: &Body<'_>) -> BitSet<Local> {
+    let mut visitor = BorrowCollector { locals: BitSet::new_empty(body.local_decls.len()) };
+    visitor.visit_body(body);
+    visitor.locals
+}
+
+struct BorrowCollector {
+    locals: BitSet<Local>,
+}
+
+impl<'tcx> Visitor<'tcx> for BorrowCollector {
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
+        self.super_rvalue(rvalue, location);
+
+        match rvalue {
+            Rvalue::AddressOf(_, borrowed_place) | Rvalue::Ref(_, _, borrowed_place) => {
+                if !borrowed_place.is_indirect() {
+                    self.locals.insert(borrowed_place.local);
+                }
+            }
+
+            Rvalue::Cast(..)
+            | Rvalue::Use(..)
+            | Rvalue::Repeat(..)
+            | Rvalue::Len(..)
+            | Rvalue::BinaryOp(..)
+            | Rvalue::CheckedBinaryOp(..)
+            | Rvalue::NullaryOp(..)
+            | Rvalue::UnaryOp(..)
+            | Rvalue::Discriminant(..)
+            | Rvalue::Aggregate(..)
+            | Rvalue::ThreadLocalRef(..) => {}
+        }
+    }
+
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
+        self.super_terminator(terminator, location);
+
+        match terminator.kind {
+            TerminatorKind::Drop { place: dropped_place, .. }
+            | TerminatorKind::DropAndReplace { place: dropped_place, .. } => {
+                self.locals.insert(dropped_place.local);
+            }
+
+            TerminatorKind::Abort
+            | TerminatorKind::Assert { .. }
+            | TerminatorKind::Call { .. }
+            | TerminatorKind::FalseEdge { .. }
+            | TerminatorKind::FalseUnwind { .. }
+            | TerminatorKind::GeneratorDrop
+            | TerminatorKind::Goto { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Return
+            | TerminatorKind::SwitchInt { .. }
+            | TerminatorKind::Unreachable
+            | TerminatorKind::Yield { .. }
+            | TerminatorKind::InlineAsm { .. } => {}
+        }
+    }
+}
+
+/// `PlaceElem::Index` only stores a `Local`, so we can't replace that with a full `Place`.
+///
+/// Collect locals used as indices so we don't generate candidates that are impossible to apply
+/// later.
+fn locals_used_as_array_index(body: &Body<'_>) -> BitSet<Local> {
+    let mut visitor = IndexCollector { locals: BitSet::new_empty(body.local_decls.len()) };
+    visitor.visit_body(body);
+    visitor.locals
+}
+
+struct IndexCollector {
+    locals: BitSet<Local>,
+}
+
+impl<'tcx> Visitor<'tcx> for IndexCollector {
+    fn visit_projection_elem(
+        &mut self,
+        local: Local,
+        proj_base: &[PlaceElem<'tcx>],
+        elem: PlaceElem<'tcx>,
+        context: PlaceContext,
+        location: Location,
+    ) {
+        if let PlaceElem::Index(i) = elem {
+            self.locals.insert(i);
+        }
+        self.super_projection_elem(local, proj_base, elem, context, location);
+    }
+}
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index 226282fe426..fc9854ba499 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -24,6 +24,7 @@ pub mod cleanup_post_borrowck;
 pub mod const_prop;
 pub mod copy_prop;
 pub mod deaggregator;
+pub mod dest_prop;
 pub mod dump_mir;
 pub mod elaborate_drops;
 pub mod generator;
@@ -467,6 +468,7 @@ fn run_optimization_passes<'tcx>(
         &simplify_comparison_integral::SimplifyComparisonIntegral,
         &simplify_try::SimplifyArmIdentity,
         &simplify_try::SimplifyBranchSame,
+        &dest_prop::DestinationPropagation,
         &copy_prop::CopyPropagation,
         &simplify_branches::SimplifyBranches::new("after-copy-prop"),
         &remove_noop_landing_pads::RemoveNoopLandingPads,
diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs
index 3673b6a4aa2..1ffb5a87c47 100644
--- a/compiler/rustc_mir/src/transform/nrvo.rs
+++ b/compiler/rustc_mir/src/transform/nrvo.rs
@@ -36,6 +36,12 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
             return;
         }
 
+        if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
+            // The `DestinationPropagation` pass runs at level 2, so this pass is redundant (and
+            // fails some asserts).
+            return;
+        }
+
         let returned_local = match local_eligible_for_nrvo(body) {
             Some(l) => l,
             None => {
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
index a137d7fadba..8b09eade067 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir
@@ -24,42 +24,42 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc17─╼ 03 00 00 00                         │ ╾──╼....
+    ╾─alloc14─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc17 (size: 48, align: 4) {
+alloc14 (size: 48, align: 4) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc7──╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
 alloc4 (size: 0, align: 4) {}
 
-alloc8 (size: 16, align: 4) {
-    ╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼....
+alloc7 (size: 16, align: 4) {
+    ╾─alloc6──╼ 03 00 00 00 ╾─alloc8──╼ 03 00 00 00 │ ╾──╼....╾──╼....
 }
 
-alloc7 (size: 3, align: 1) {
+alloc6 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc9 (size: 3, align: 1) {
+alloc8 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc13 (size: 24, align: 4) {
-    0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼....
-    0x10 │ ╾─alloc15─╼ 04 00 00 00                         │ ╾──╼....
+alloc11 (size: 24, align: 4) {
+    0x00 │ ╾─alloc10─╼ 03 00 00 00 ╾─alloc12─╼ 03 00 00 00 │ ╾──╼....╾──╼....
+    0x10 │ ╾─alloc13─╼ 04 00 00 00                         │ ╾──╼....
 }
 
-alloc12 (size: 3, align: 1) {
+alloc10 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
-alloc14 (size: 3, align: 1) {
+alloc12 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc15 (size: 4, align: 1) {
+alloc13 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
index ef98cf9c091..2853a0ac18b 100644
--- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir
@@ -24,46 +24,46 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc17 (size: 72, align: 8) {
+alloc14 (size: 72, align: 8) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc7────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc11───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
 alloc4 (size: 0, align: 8) {}
 
-alloc8 (size: 32, align: 8) {
-    0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc7 (size: 32, align: 8) {
+    0x00 │ ╾───────alloc6────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc7 (size: 3, align: 1) {
+alloc6 (size: 3, align: 1) {
     66 6f 6f                                        │ foo
 }
 
-alloc9 (size: 3, align: 1) {
+alloc8 (size: 3, align: 1) {
     62 61 72                                        │ bar
 }
 
-alloc13 (size: 48, align: 8) {
-    0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
+alloc11 (size: 48, align: 8) {
+    0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x10 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x20 │ ╾───────alloc13───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc12 (size: 3, align: 1) {
+alloc10 (size: 3, align: 1) {
     6d 65 68                                        │ meh
 }
 
-alloc14 (size: 3, align: 1) {
+alloc12 (size: 3, align: 1) {
     6d 6f 70                                        │ mop
 }
 
-alloc15 (size: 4, align: 1) {
+alloc13 (size: 4, align: 1) {
     6d c3 b6 70                                     │ m..p
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
index c4f10064890..710ffeeda07 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir
@@ -24,41 +24,41 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 8, align: 4) {
-    ╾─alloc23─╼ 03 00 00 00                         │ ╾──╼....
+    ╾─alloc20─╼ 03 00 00 00                         │ ╾──╼....
 }
 
-alloc23 (size: 48, align: 4) {
+alloc20 (size: 48, align: 4) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼....
-    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 02 00 00 00 │ ....░░░░╾──╼....
-    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc21─╼ 03 00 00 00 │ ....*...╾──╼....
+    0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 02 00 00 00 │ ....░░░░╾──╼....
+    0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc19─╼ 03 00 00 00 │ ....*...╾──╼....
 }
 
 alloc8 (size: 0, align: 4) {}
 
-alloc13 (size: 8, align: 4) {
-    ╾─alloc11─╼ ╾─alloc12─╼                         │ ╾──╼╾──╼
+alloc12 (size: 8, align: 4) {
+    ╾─alloc10─╼ ╾─alloc11─╼                         │ ╾──╼╾──╼
 }
 
-alloc11 (size: 1, align: 1) {
+alloc10 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc12 (size: 1, align: 1) {
+alloc11 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc21 (size: 12, align: 4) {
-    ╾─a17+0x3─╼ ╾─alloc18─╼ ╾─a20+0x2─╼             │ ╾──╼╾──╼╾──╼
+alloc19 (size: 12, align: 4) {
+    ╾─a15+0x3─╼ ╾─alloc16─╼ ╾─a18+0x2─╼             │ ╾──╼╾──╼╾──╼
 }
 
-alloc17 (size: 4, align: 1) {
+alloc15 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc18 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc20 (size: 4, align: 1) {
+alloc18 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
index b16b85c4e95..97a7f76f6bb 100644
--- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir
@@ -24,44 +24,44 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 16, align: 8) {
-    ╾───────alloc23───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
+    ╾───────alloc20───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
 }
 
-alloc23 (size: 72, align: 8) {
+alloc20 (size: 72, align: 8) {
     0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼
     0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
-    0x20 │ ╾───────alloc13───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
-    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc21───────╼ │ ....*...╾──────╼
+    0x20 │ ╾───────alloc12───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
+    0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc19───────╼ │ ....*...╾──────╼
     0x40 │ 03 00 00 00 00 00 00 00                         │ ........
 }
 
 alloc8 (size: 0, align: 8) {}
 
-alloc13 (size: 16, align: 8) {
-    ╾───────alloc11───────╼ ╾───────alloc12───────╼ │ ╾──────╼╾──────╼
+alloc12 (size: 16, align: 8) {
+    ╾───────alloc10───────╼ ╾───────alloc11───────╼ │ ╾──────╼╾──────╼
 }
 
-alloc11 (size: 1, align: 1) {
+alloc10 (size: 1, align: 1) {
     05                                              │ .
 }
 
-alloc12 (size: 1, align: 1) {
+alloc11 (size: 1, align: 1) {
     06                                              │ .
 }
 
-alloc21 (size: 24, align: 8) {
-    0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼
-    0x10 │ ╾─────alloc20+0x2─────╼                         │ ╾──────╼
+alloc19 (size: 24, align: 8) {
+    0x00 │ ╾─────alloc15+0x3─────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
+    0x10 │ ╾─────alloc18+0x2─────╼                         │ ╾──────╼
 }
 
-alloc17 (size: 4, align: 1) {
+alloc15 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
 
-alloc18 (size: 1, align: 1) {
+alloc16 (size: 1, align: 1) {
     2a                                              │ *
 }
 
-alloc20 (size: 4, align: 1) {
+alloc18 (size: 4, align: 1) {
     2a 45 15 6f                                     │ *E.o
 }
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
index 99d3a278d69..19d6c51bc75 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir
@@ -24,10 +24,10 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 4, align: 4) {
-    ╾─alloc9──╼                                     │ ╾──╼
+    ╾─alloc3──╼                                     │ ╾──╼
 }
 
-alloc9 (size: 168, align: 1) {
+alloc3 (size: 168, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
     0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc4──╼ │ ............╾──╼
     0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
index d6e49892d4c..94388b08c0e 100644
--- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
+++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir
@@ -24,10 +24,10 @@ fn main() -> () {
 }
 
 alloc0 (static: FOO, size: 8, align: 8) {
-    ╾───────alloc9────────╼                         │ ╾──────╼
+    ╾───────alloc3────────╼                         │ ╾──────╼
 }
 
-alloc9 (size: 180, align: 1) {
+alloc3 (size: 180, align: 1) {
     0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
     0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc4── │ ............╾───
     0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............
diff --git a/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff b/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
index f2838638aca..1f3e559c1b7 100644
--- a/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation.test.CopyPropagation.diff
@@ -6,19 +6,14 @@
       let mut _0: u32;                     // return place in scope 0 at $DIR/copy_propagation.rs:3:20: 3:23
       let _2: u32;                         // in scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
       scope 1 {
--         debug y => _2;                   // in scope 1 at $DIR/copy_propagation.rs:4:9: 4:10
-+         debug y => _1;                   // in scope 1 at $DIR/copy_propagation.rs:4:9: 4:10
+          debug y => _0;                   // in scope 1 at $DIR/copy_propagation.rs:4:9: 4:10
       }
   
       bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
--         _2 = _1;                         // scope 0 at $DIR/copy_propagation.rs:4:13: 4:14
--         _0 = _2;                         // scope 1 at $DIR/copy_propagation.rs:5:5: 5:6
--         StorageDead(_2);                 // scope 0 at $DIR/copy_propagation.rs:6:1: 6:2
-+         nop;                             // scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
-+         nop;                             // scope 0 at $DIR/copy_propagation.rs:4:13: 4:14
-+         _0 = _1;                         // scope 1 at $DIR/copy_propagation.rs:5:5: 5:6
-+         nop;                             // scope 0 at $DIR/copy_propagation.rs:6:1: 6:2
+          nop;                             // scope 0 at $DIR/copy_propagation.rs:4:9: 4:10
+          _0 = _1;                         // scope 0 at $DIR/copy_propagation.rs:4:13: 4:14
+          nop;                             // scope 1 at $DIR/copy_propagation.rs:5:5: 5:6
+          nop;                             // scope 0 at $DIR/copy_propagation.rs:6:1: 6:2
           return;                          // scope 0 at $DIR/copy_propagation.rs:6:2: 6:2
       }
   }
diff --git a/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
index a4d60ae25d0..8aab2299d26 100644
--- a/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.arg_src.CopyPropagation.diff
@@ -6,15 +6,15 @@
       let mut _0: i32;                     // return place in scope 0 at $DIR/copy_propagation_arg.rs:27:27: 27:30
       let _2: i32;                         // in scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10
       scope 1 {
-          debug y => _2;                   // in scope 1 at $DIR/copy_propagation_arg.rs:28:9: 28:10
+          debug y => _0;                   // in scope 1 at $DIR/copy_propagation_arg.rs:28:9: 28:10
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10
-          _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:28:13: 28:14
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:28:9: 28:10
+          _0 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:28:13: 28:14
           _1 = const 123_i32;              // scope 1 at $DIR/copy_propagation_arg.rs:29:5: 29:12
-          _0 = _2;                         // scope 1 at $DIR/copy_propagation_arg.rs:30:5: 30:6
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:31:1: 31:2
+          nop;                             // scope 1 at $DIR/copy_propagation_arg.rs:30:5: 30:6
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:31:1: 31:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:31:2: 31:2
       }
   }
diff --git a/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
index b20003bd7c6..1ea51fec710 100644
--- a/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.baz.CopyPropagation.diff
@@ -7,10 +7,10 @@
       let mut _2: i32;                     // in scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
-          _2 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
-          _1 = move _2;                    // scope 0 at $DIR/copy_propagation_arg.rs:23:5: 23:10
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:5: 23:10
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:23:9: 23:10
           _0 = const ();                   // scope 0 at $DIR/copy_propagation_arg.rs:21:20: 24:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:24:2: 24:2
       }
diff --git a/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
index d07a4c0541e..48ab37a239c 100644
--- a/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
+++ b/src/test/mir-opt/copy_propagation_arg.foo.CopyPropagation.diff
@@ -8,10 +8,10 @@
       let mut _3: u8;                      // in scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
           StorageLive(_3);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:11:15: 11:16
-          _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
+          _1 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:11:9: 11:17
                                            // mir::Constant
                                            // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(Scalar(<ZST>)) }
@@ -19,8 +19,8 @@
   
       bb1: {
           StorageDead(_3);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17
-          _1 = move _2;                    // scope 0 at $DIR/copy_propagation_arg.rs:11:5: 11:17
-          StorageDead(_2);                 // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:11:5: 11:17
+          nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:11:16: 11:17
           _0 = const ();                   // scope 0 at $DIR/copy_propagation_arg.rs:9:19: 12:2
           return;                          // scope 0 at $DIR/copy_propagation_arg.rs:12:2: 12:2
       }
diff --git a/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
new file mode 100644
index 00000000000..9c213eaed3c
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/branch.main.DestinationPropagation.diff
@@ -0,0 +1,73 @@
+- // MIR for `main` before DestinationPropagation
++ // MIR for `main` after DestinationPropagation
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/branch.rs:12:11: 12:11
+      let _1: i32;                         // in scope 0 at $DIR/branch.rs:13:9: 13:10
+      let mut _3: bool;                    // in scope 0 at $DIR/branch.rs:15:16: 15:22
+      let _4: i32;                         // in scope 0 at $DIR/branch.rs:18:9: 18:14
+      scope 1 {
+-         debug x => _1;                   // in scope 1 at $DIR/branch.rs:13:9: 13:10
++         debug x => _2;                   // in scope 1 at $DIR/branch.rs:13:9: 13:10
+          let _2: i32;                     // in scope 1 at $DIR/branch.rs:15:9: 15:10
+          scope 2 {
+              debug y => _2;               // in scope 2 at $DIR/branch.rs:15:9: 15:10
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_1);                 // scope 0 at $DIR/branch.rs:13:9: 13:10
+-         _1 = val() -> bb1;               // scope 0 at $DIR/branch.rs:13:13: 13:18
++         nop;                             // scope 0 at $DIR/branch.rs:13:9: 13:10
++         _2 = val() -> bb1;               // scope 0 at $DIR/branch.rs:13:13: 13:18
+                                           // mir::Constant
+                                           // + span: $DIR/branch.rs:13:13: 13:16
+                                           // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+-         StorageLive(_2);                 // scope 1 at $DIR/branch.rs:15:9: 15:10
++         nop;                             // scope 1 at $DIR/branch.rs:15:9: 15:10
+          StorageLive(_3);                 // scope 1 at $DIR/branch.rs:15:16: 15:22
+          _3 = cond() -> bb2;              // scope 1 at $DIR/branch.rs:15:16: 15:22
+                                           // mir::Constant
+                                           // + span: $DIR/branch.rs:15:16: 15:20
+                                           // + literal: Const { ty: fn() -> bool {cond}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb2: {
+          switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 1 at $DIR/branch.rs:15:13: 20:6
+      }
+  
+      bb3: {
+          StorageLive(_4);                 // scope 1 at $DIR/branch.rs:18:9: 18:14
+          _4 = val() -> bb5;               // scope 1 at $DIR/branch.rs:18:9: 18:14
+                                           // mir::Constant
+                                           // + span: $DIR/branch.rs:18:9: 18:12
+                                           // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb4: {
+-         _2 = _1;                         // scope 1 at $DIR/branch.rs:16:9: 16:10
++         nop;                             // scope 1 at $DIR/branch.rs:16:9: 16:10
+          goto -> bb6;                     // scope 1 at $DIR/branch.rs:15:13: 20:6
+      }
+  
+      bb5: {
+          StorageDead(_4);                 // scope 1 at $DIR/branch.rs:18:14: 18:15
+-         _2 = _1;                         // scope 1 at $DIR/branch.rs:19:9: 19:10
++         nop;                             // scope 1 at $DIR/branch.rs:19:9: 19:10
+          goto -> bb6;                     // scope 1 at $DIR/branch.rs:15:13: 20:6
+      }
+  
+      bb6: {
+          StorageDead(_3);                 // scope 1 at $DIR/branch.rs:20:6: 20:7
+          _0 = const ();                   // scope 0 at $DIR/branch.rs:12:11: 21:2
+-         StorageDead(_2);                 // scope 1 at $DIR/branch.rs:21:1: 21:2
+-         StorageDead(_1);                 // scope 0 at $DIR/branch.rs:21:1: 21:2
++         nop;                             // scope 1 at $DIR/branch.rs:21:1: 21:2
++         nop;                             // scope 0 at $DIR/branch.rs:21:1: 21:2
+          return;                          // scope 0 at $DIR/branch.rs:21:2: 21:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/branch.rs b/src/test/mir-opt/dest-prop/branch.rs
new file mode 100644
index 00000000000..7e0e40671dd
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/branch.rs
@@ -0,0 +1,21 @@
+//! Tests that assignment in both branches of an `if` are eliminated.
+
+fn val() -> i32 {
+    1
+}
+
+fn cond() -> bool {
+    true
+}
+
+// EMIT_MIR branch.main.DestinationPropagation.diff
+fn main() {
+    let x = val();
+
+    let y = if cond() {
+        x
+    } else {
+        val();
+        x
+    };
+}
diff --git a/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
new file mode 100644
index 00000000000..dd717c1b9c3
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
@@ -0,0 +1,76 @@
+- // MIR for `main` before DestinationPropagation
++ // MIR for `main` after DestinationPropagation
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/cycle.rs:8:11: 8:11
+      let mut _1: i32;                     // in scope 0 at $DIR/cycle.rs:9:9: 9:14
+      let mut _4: i32;                     // in scope 0 at $DIR/cycle.rs:12:9: 12:10
+      let _5: ();                          // in scope 0 at $DIR/cycle.rs:14:5: 14:12
+      let mut _6: i32;                     // in scope 0 at $DIR/cycle.rs:14:10: 14:11
+      scope 1 {
+-         debug x => _1;                   // in scope 1 at $DIR/cycle.rs:9:9: 9:14
++         debug x => _4;                   // in scope 1 at $DIR/cycle.rs:9:9: 9:14
+          let _2: i32;                     // in scope 1 at $DIR/cycle.rs:10:9: 10:10
+          scope 2 {
+-             debug y => _2;               // in scope 2 at $DIR/cycle.rs:10:9: 10:10
++             debug y => _4;               // in scope 2 at $DIR/cycle.rs:10:9: 10:10
+              let _3: i32;                 // in scope 2 at $DIR/cycle.rs:11:9: 11:10
+              scope 3 {
+-                 debug z => _3;           // in scope 3 at $DIR/cycle.rs:11:9: 11:10
++                 debug z => _4;           // in scope 3 at $DIR/cycle.rs:11:9: 11:10
+                  scope 4 {
+                      debug _x => _6;      // in scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_1);                 // scope 0 at $DIR/cycle.rs:9:9: 9:14
+-         _1 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:9:17: 9:22
++         nop;                             // scope 0 at $DIR/cycle.rs:9:9: 9:14
++         _4 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:9:17: 9:22
+                                           // mir::Constant
+                                           // + span: $DIR/cycle.rs:9:17: 9:20
+                                           // + literal: Const { ty: fn() -> i32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+-         StorageLive(_2);                 // scope 1 at $DIR/cycle.rs:10:9: 10:10
+-         _2 = _1;                         // scope 1 at $DIR/cycle.rs:10:13: 10:14
+-         StorageLive(_3);                 // scope 2 at $DIR/cycle.rs:11:9: 11:10
+-         _3 = _2;                         // scope 2 at $DIR/cycle.rs:11:13: 11:14
+-         StorageLive(_4);                 // scope 3 at $DIR/cycle.rs:12:9: 12:10
+-         _4 = _3;                         // scope 3 at $DIR/cycle.rs:12:9: 12:10
+-         _1 = move _4;                    // scope 3 at $DIR/cycle.rs:12:5: 12:10
+-         StorageDead(_4);                 // scope 3 at $DIR/cycle.rs:12:9: 12:10
++         nop;                             // scope 1 at $DIR/cycle.rs:10:9: 10:10
++         nop;                             // scope 1 at $DIR/cycle.rs:10:13: 10:14
++         nop;                             // scope 2 at $DIR/cycle.rs:11:9: 11:10
++         nop;                             // scope 2 at $DIR/cycle.rs:11:13: 11:14
++         nop;                             // scope 3 at $DIR/cycle.rs:12:9: 12:10
++         nop;                             // scope 3 at $DIR/cycle.rs:12:9: 12:10
++         nop;                             // scope 3 at $DIR/cycle.rs:12:5: 12:10
++         nop;                             // scope 3 at $DIR/cycle.rs:12:9: 12:10
+          StorageLive(_5);                 // scope 3 at $DIR/cycle.rs:14:5: 14:12
+          StorageLive(_6);                 // scope 3 at $DIR/cycle.rs:14:10: 14:11
+-         _6 = _1;                         // scope 3 at $DIR/cycle.rs:14:10: 14:11
++         _6 = _4;                         // scope 3 at $DIR/cycle.rs:14:10: 14:11
+          _5 = const ();                   // scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+          drop(_6) -> bb2;                 // scope 4 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+      }
+  
+      bb2: {
+          StorageDead(_6);                 // scope 3 at $DIR/cycle.rs:14:11: 14:12
+          StorageDead(_5);                 // scope 3 at $DIR/cycle.rs:14:12: 14:13
+          _0 = const ();                   // scope 0 at $DIR/cycle.rs:8:11: 15:2
+-         StorageDead(_3);                 // scope 2 at $DIR/cycle.rs:15:1: 15:2
+-         StorageDead(_2);                 // scope 1 at $DIR/cycle.rs:15:1: 15:2
+-         StorageDead(_1);                 // scope 0 at $DIR/cycle.rs:15:1: 15:2
++         nop;                             // scope 2 at $DIR/cycle.rs:15:1: 15:2
++         nop;                             // scope 1 at $DIR/cycle.rs:15:1: 15:2
++         nop;                             // scope 0 at $DIR/cycle.rs:15:1: 15:2
+          return;                          // scope 0 at $DIR/cycle.rs:15:2: 15:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/cycle.rs b/src/test/mir-opt/dest-prop/cycle.rs
new file mode 100644
index 00000000000..7fbffb13359
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/cycle.rs
@@ -0,0 +1,15 @@
+//! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code.
+
+fn val() -> i32 {
+    1
+}
+
+// EMIT_MIR cycle.main.DestinationPropagation.diff
+fn main() {
+    let mut x = val();
+    let y = x;
+    let z = y;
+    x = z;
+
+    drop(x);
+}
diff --git a/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
new file mode 100644
index 00000000000..1277c51f2a0
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/simple.nrvo.DestinationPropagation.diff
@@ -0,0 +1,45 @@
+- // MIR for `nrvo` before DestinationPropagation
++ // MIR for `nrvo` after DestinationPropagation
+  
+  fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] {
+      debug init => _1;                    // in scope 0 at $DIR/simple.rs:4:9: 4:13
+      let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/simple.rs:4:39: 4:49
+      let mut _2: [u8; 1024];              // in scope 0 at $DIR/simple.rs:5:9: 5:16
+      let _3: ();                          // in scope 0 at $DIR/simple.rs:6:5: 6:19
+      let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:6:5: 6:9
+      let mut _5: &mut [u8; 1024];         // in scope 0 at $DIR/simple.rs:6:10: 6:18
+      let mut _6: &mut [u8; 1024];         // in scope 0 at $DIR/simple.rs:6:10: 6:18
+      scope 1 {
+-         debug buf => _2;                 // in scope 1 at $DIR/simple.rs:5:9: 5:16
++         debug buf => _0;                 // in scope 1 at $DIR/simple.rs:5:9: 5:16
+      }
+  
+      bb0: {
+-         StorageLive(_2);                 // scope 0 at $DIR/simple.rs:5:9: 5:16
+-         _2 = [const 0_u8; 1024];         // scope 0 at $DIR/simple.rs:5:19: 5:28
++         nop;                             // scope 0 at $DIR/simple.rs:5:9: 5:16
++         _0 = [const 0_u8; 1024];         // scope 0 at $DIR/simple.rs:5:19: 5:28
+          StorageLive(_3);                 // scope 1 at $DIR/simple.rs:6:5: 6:19
+          StorageLive(_4);                 // scope 1 at $DIR/simple.rs:6:5: 6:9
+          _4 = _1;                         // scope 1 at $DIR/simple.rs:6:5: 6:9
+          StorageLive(_5);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
+          StorageLive(_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
+-         _6 = &mut _2;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
++         _6 = &mut _0;                    // scope 1 at $DIR/simple.rs:6:10: 6:18
+          _5 = &mut (*_6);                 // scope 1 at $DIR/simple.rs:6:10: 6:18
+          _3 = move _4(move _5) -> bb1;    // scope 1 at $DIR/simple.rs:6:5: 6:19
+      }
+  
+      bb1: {
+          StorageDead(_5);                 // scope 1 at $DIR/simple.rs:6:18: 6:19
+          StorageDead(_4);                 // scope 1 at $DIR/simple.rs:6:18: 6:19
+          StorageDead(_6);                 // scope 1 at $DIR/simple.rs:6:19: 6:20
+          StorageDead(_3);                 // scope 1 at $DIR/simple.rs:6:19: 6:20
+-         _0 = _2;                         // scope 1 at $DIR/simple.rs:7:5: 7:8
+-         StorageDead(_2);                 // scope 0 at $DIR/simple.rs:8:1: 8:2
++         nop;                             // scope 1 at $DIR/simple.rs:7:5: 7:8
++         nop;                             // scope 0 at $DIR/simple.rs:8:1: 8:2
+          return;                          // scope 0 at $DIR/simple.rs:8:2: 8:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/simple.rs b/src/test/mir-opt/dest-prop/simple.rs
new file mode 100644
index 00000000000..4655f966998
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/simple.rs
@@ -0,0 +1,14 @@
+//! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too.
+
+// EMIT_MIR simple.nrvo.DestinationPropagation.diff
+fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
+    let mut buf = [0; 1024];
+    init(&mut buf);
+    buf
+}
+
+fn main() {
+    let _ = nrvo(|buf| {
+        buf[4] = 4;
+    });
+}
diff --git a/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
new file mode 100644
index 00000000000..871f6e35043
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff
@@ -0,0 +1,46 @@
+- // MIR for `main` before DestinationPropagation
++ // MIR for `main` after DestinationPropagation
+  
+  fn main() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/union.rs:8:11: 8:11
+      let _1: main::Un;                    // in scope 0 at $DIR/union.rs:13:9: 13:11
+      let mut _2: u32;                     // in scope 0 at $DIR/union.rs:13:23: 13:28
+      let _3: ();                          // in scope 0 at $DIR/union.rs:15:5: 15:27
+      let mut _4: u32;                     // in scope 0 at $DIR/union.rs:15:10: 15:26
+      scope 1 {
+          debug un => _1;                  // in scope 1 at $DIR/union.rs:13:9: 13:11
+          scope 2 {
+          }
+          scope 3 {
+              debug _x => _4;              // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+          }
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/union.rs:13:9: 13:11
+          StorageLive(_2);                 // scope 0 at $DIR/union.rs:13:23: 13:28
+          _2 = val() -> bb1;               // scope 0 at $DIR/union.rs:13:23: 13:28
+                                           // mir::Constant
+                                           // + span: $DIR/union.rs:13:23: 13:26
+                                           // + literal: Const { ty: fn() -> u32 {val}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          (_1.0: u32) = move _2;           // scope 0 at $DIR/union.rs:13:14: 13:30
+          StorageDead(_2);                 // scope 0 at $DIR/union.rs:13:29: 13:30
+          StorageLive(_3);                 // scope 1 at $DIR/union.rs:15:5: 15:27
+          StorageLive(_4);                 // scope 1 at $DIR/union.rs:15:10: 15:26
+          _4 = (_1.0: u32);                // scope 2 at $DIR/union.rs:15:19: 15:24
+          _3 = const ();                   // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+          drop(_4) -> bb2;                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+      }
+  
+      bb2: {
+          StorageDead(_4);                 // scope 1 at $DIR/union.rs:15:26: 15:27
+          StorageDead(_3);                 // scope 1 at $DIR/union.rs:15:27: 15:28
+          _0 = const ();                   // scope 0 at $DIR/union.rs:8:11: 16:2
+          StorageDead(_1);                 // scope 0 at $DIR/union.rs:16:1: 16:2
+          return;                          // scope 0 at $DIR/union.rs:16:2: 16:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/dest-prop/union.rs b/src/test/mir-opt/dest-prop/union.rs
new file mode 100644
index 00000000000..b9d831389e8
--- /dev/null
+++ b/src/test/mir-opt/dest-prop/union.rs
@@ -0,0 +1,16 @@
+//! Tests that projections through unions cancel `DestinationPropagation`.
+
+fn val() -> u32 {
+    1
+}
+
+// EMIT_MIR union.main.DestinationPropagation.diff
+fn main() {
+    union Un {
+        us: u32,
+    }
+
+    let un = Un { us: val() };
+
+    drop(unsafe { un.us });
+}
diff --git a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
index 0258e3c2e4b..ab194cf532f 100644
--- a/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir
@@ -10,15 +10,14 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
     let mut _6: &[closure@foo<T>::{{closure}}#0 q:&i32, t:&T]; // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:6
     let mut _7: (i32,);                  // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
     let mut _8: i32;                     // in scope 0 at $DIR/inline-closure-captures.rs:12:7: 12:8
-    let mut _11: i32;                    // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
+    let mut _10: i32;                    // in scope 0 at $DIR/inline-closure-captures.rs:12:5: 12:9
     scope 1 {
         debug x => _3;                   // in scope 1 at $DIR/inline-closure-captures.rs:11:9: 11:10
         scope 2 {
-            debug _q => _11;             // in scope 2 at $DIR/inline-closure-captures.rs:11:14: 11:16
+            debug _q => _10;             // in scope 2 at $DIR/inline-closure-captures.rs:11:14: 11:16
             debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline-closure-captures.rs:10:23: 10:24
             debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline-closure-captures.rs:10:17: 10:18
-            let mut _9: i32;             // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
-            let mut _10: T;              // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
+            let mut _9: T;               // in scope 2 at $DIR/inline-closure-captures.rs:12:5: 12:9
         }
     }
 
@@ -38,17 +37,14 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
         StorageLive(_8);                 // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
         _8 = _2;                         // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
         (_7.0: i32) = move _8;           // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
-        StorageLive(_11);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
-        _11 = move (_7.0: i32);          // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
-        StorageLive(_9);                 // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
-        _9 = (*((*_6).0: &i32));         // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
-        StorageLive(_10);                // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
-        _10 = (*((*_6).1: &T));          // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
-        (_0.0: i32) = move _9;           // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
-        (_0.1: T) = move _10;            // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
-        StorageDead(_10);                // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24
+        StorageLive(_10);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
+        _10 = move (_7.0: i32);          // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
+        (_0.0: i32) = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
+        StorageLive(_9);                 // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
+        _9 = (*((*_6).1: &T));           // scope 2 at $DIR/inline-closure-captures.rs:11:22: 11:23
+        (_0.1: T) = move _9;             // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
         StorageDead(_9);                 // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24
-        StorageDead(_11);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
+        StorageDead(_10);                // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
         StorageDead(_8);                 // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
         StorageDead(_7);                 // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
         StorageDead(_6);                 // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
index f86755cfa7f..a8662b96566 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.32bit.diff
@@ -3,66 +3,59 @@
   
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11
-      let mut _1: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-      let _2: i32;                         // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-      let mut _4: i32;                     // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27
-      let mut _5: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _6: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _9: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _11: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _12: &std::fmt::Arguments;       // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _13: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _14: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _16: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _17: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _18: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _19: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _20: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _21: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _24: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _25: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _26: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _1: i32;                         // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
+      let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+      let mut _4: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _5: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _6: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _7: i32;                     // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _8: &std::fmt::Arguments;    // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _9: std::fmt::Arguments;         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _10: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _11: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _12: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _13: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _14: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _17: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
       scope 1 {
-          debug split => _2;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
+          debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _3: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
           scope 3 {
               debug _prev => _3;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
-              let _7: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let _8: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
-                  debug left_val => _7;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  debug right_val => _8;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _22: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _23: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug right_val => _15;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _22;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg0 => _20;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       debug arg1 => _23;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       scope 6 {
-                          debug x => _22;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _25;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _28: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _29: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug x => _20;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          debug f => _19;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _18: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _19: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _20: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                       scope 8 {
                           debug x => _23;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _27;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _31: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug f => _22;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _21: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _22: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _23: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                   }
                   scope 10 {
-                      debug pieces => _14; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      debug args => _15;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      let mut _32: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug pieces => (_9.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      debug args => _25;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      let mut _24: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      let mut _25: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
                   }
               }
           }
       }
       scope 2 {
-          debug v => _2;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
+          debug v => _1;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
       }
       scope 7 {
       }
@@ -70,138 +63,108 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          ((_1 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          discriminant(_1) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          _2 = ((_1 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
-          StorageLive(_3);                 // scope 1 at $DIR/issue-73223.rs:7:9: 7:14
-          StorageLive(_4);                 // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          _4 = _2;                         // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          ((_3 as Some).0: i32) = move _4; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
+          StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          _1 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
+          StorageDead(_2);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
+          ((_3 as Some).0: i32) = _1;      // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
           discriminant(_3) = 1;            // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
-          StorageDead(_4);                 // scope 1 at $DIR/issue-73223.rs:7:27: 7:28
-          StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _6 = &_2;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.0: &i32) = move _6;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.0: &i32) = &_1;              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
-          StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _7 = (_5.0: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _8 = (_5.1: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _11 = (*_7);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _10 = Eq(move _11, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _9 = Not(move _10);              // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_9) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _13 = (_4.0: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = (_4.1: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _7 = (*_13);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _6 = Eq(move _7, const 1_i32);   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _5 = Not(move _6);               // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(_5) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
-          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_3);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
           return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
       }
   
       bb2: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _14 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_9.0: &[&str]) = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
-          StorageLive(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_18);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _19 = &_20;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _21 = &_8;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_18.0: &&i32) = move _19;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_18.1: &&i32) = move _21;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_21);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _22 = (_18.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _23 = (_18.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_11);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_12.0: &&i32) = &_13;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _14 = &_15;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.1: &&i32) = move _14;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_14);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _20 = (_12.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _23 = (_12.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _28 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _18 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _19) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb3: {
-          StorageLive(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _29 = transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_16.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _20) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb4: {
-          (_24.0: &core::fmt::Opaque) = move _29; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_24.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _28; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageLive(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _18; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _22 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _30 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _21 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _22) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          StorageLive(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _31 = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_17.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          (_26.0: &core::fmt::Opaque) = move _31; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _17 = [move _24, move _26];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _16 = &_17;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _15 = move _16 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          discriminant(_32) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.0: &[&str]) = move _14;     // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _32; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _12);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_17.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _21; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _11 = [move _16, move _17];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _10 = &_11;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _25 = move _10 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          discriminant(_24) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _24; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.2: &[std::fmt::ArgumentV1]) = move _25; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _8 = &_9;                        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          begin_panic_fmt(move _8);        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
index f86755cfa7f..a8662b96566 100644
--- a/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.PreCodegen.64bit.diff
@@ -3,66 +3,59 @@
   
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/issue-73223.rs:1:11: 1:11
-      let mut _1: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-      let _2: i32;                         // in scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-      let mut _4: i32;                     // in scope 0 at $DIR/issue-73223.rs:7:22: 7:27
-      let mut _5: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _6: &i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _9: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _10: bool;                   // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _11: i32;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _12: &std::fmt::Arguments;       // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _13: std::fmt::Arguments;        // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _14: &[&str];                // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _15: &[std::fmt::ArgumentV1]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _16: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let _17: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _18: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _19: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let _20: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _21: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _24: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _25: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-      let mut _26: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
-      let mut _27: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _1: i32;                         // in scope 0 at $DIR/issue-73223.rs:2:9: 2:14
+      let mut _2: std::option::Option<i32>; // in scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+      let mut _4: (&i32, &i32);            // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _5: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _6: bool;                    // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _7: i32;                     // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _8: &std::fmt::Arguments;    // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _9: std::fmt::Arguments;         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _10: &[std::fmt::ArgumentV1; 2]; // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _11: [std::fmt::ArgumentV1; 2];  // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _12: (&&i32, &&i32);         // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let _13: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _14: &&i32;                  // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let _15: &i32;                       // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+      let mut _16: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
+      let mut _17: std::fmt::ArgumentV1;   // in scope 0 at $SRC_DIR/std/src/macros.rs:LL:COL
       scope 1 {
-          debug split => _2;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
+          debug split => _1;               // in scope 1 at $DIR/issue-73223.rs:2:9: 2:14
           let _3: std::option::Option<i32>; // in scope 1 at $DIR/issue-73223.rs:7:9: 7:14
           scope 3 {
               debug _prev => _3;           // in scope 3 at $DIR/issue-73223.rs:7:9: 7:14
-              let _7: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-              let _8: &i32;                // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
               scope 4 {
-                  debug left_val => _7;    // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  debug right_val => _8;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _22: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-                  let _23: &&i32;          // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug left_val => _13;   // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                  debug right_val => _15;  // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                   scope 5 {
-                      debug arg0 => _22;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+                      debug arg0 => _20;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       debug arg1 => _23;   // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                       scope 6 {
-                          debug x => _22;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _25;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _28: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _29: &core::fmt::Opaque; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug x => _20;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          debug f => _19;  // in scope 6 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _18: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _19: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _20: &&i32; // in scope 6 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                       scope 8 {
                           debug x => _23;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          debug f => _27;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                          let mut _30: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
-                          let mut _31: &core::fmt::Opaque; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          debug f => _22;  // in scope 8 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                          let mut _21: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _22: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
+                          let mut _23: &&i32; // in scope 8 at $SRC_DIR/std/src/macros.rs:LL:COL
                       }
                   }
                   scope 10 {
-                      debug pieces => _14; // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      debug args => _15;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-                      let mut _32: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      debug pieces => (_9.0: &[&str]); // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      debug args => _25;   // in scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+                      let mut _24: std::option::Option<&[std::fmt::rt::v1::Argument]>; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
+                      let mut _25: &[std::fmt::ArgumentV1]; // in scope 10 at $SRC_DIR/std/src/macros.rs:LL:COL
                   }
               }
           }
       }
       scope 2 {
-          debug v => _2;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
+          debug v => _1;                   // in scope 2 at $DIR/issue-73223.rs:3:14: 3:15
       }
       scope 7 {
       }
@@ -70,138 +63,108 @@
       }
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          ((_1 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          discriminant(_1) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
-          _2 = ((_1 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
-          StorageDead(_1);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
-          StorageLive(_3);                 // scope 1 at $DIR/issue-73223.rs:7:9: 7:14
-          StorageLive(_4);                 // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          _4 = _2;                         // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
-          ((_3 as Some).0: i32) = move _4; // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
+          StorageLive(_2);                 // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:2:23: 2:30
+          _1 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:3:14: 3:15
+          StorageDead(_2);                 // scope 0 at $DIR/issue-73223.rs:5:6: 5:7
+          ((_3 as Some).0: i32) = _1;      // scope 1 at $DIR/issue-73223.rs:7:22: 7:27
           discriminant(_3) = 1;            // scope 1 at $DIR/issue-73223.rs:7:17: 7:28
-          StorageDead(_4);                 // scope 1 at $DIR/issue-73223.rs:7:27: 7:28
-          StorageLive(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _6 = &_2;                        // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.0: &i32) = move _6;          // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_5.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.0: &i32) = &_1;              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_4.1: &i32) = const main::promoted[1]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &i32
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &i32, val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[1])) }
-          StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _7 = (_5.0: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _8 = (_5.1: &i32);               // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _11 = (*_7);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _10 = Eq(move _11, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _9 = Not(move _10);              // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(_9) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _13 = (_4.0: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _15 = (_4.1: &i32);              // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _7 = (*_13);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _6 = Eq(move _7, const 1_i32);   // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _5 = Not(move _6);               // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(_5) -> [false: bb1, otherwise: bb2]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
-          StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_7);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageDead(_5);                 // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageDead(_5);                 // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _0 = const ();                   // scope 0 at $DIR/issue-73223.rs:1:11: 9:2
-          StorageDead(_3);                 // scope 1 at $DIR/issue-73223.rs:9:1: 9:2
           return;                          // scope 0 at $DIR/issue-73223.rs:9:2: 9:2
       }
   
       bb2: {
-          StorageLive(_13);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _14 = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_9.0: &[&str]) = const main::promoted[0] as &[&str] (Pointer(Unsize)); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // ty::Const
                                            // + ty: &[&str; 3]
                                            // + val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0]))
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: &[&str; 3], val: Unevaluated(WithOptConstParam { did: DefId(0:3 ~ issue_73223[317d]::main[0]), const_param_did: None }, [], Some(promoted[0])) }
-          StorageLive(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_18);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_19);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _20 = _7;                        // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _19 = &_20;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_21);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _21 = &_8;                       // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          (_18.0: &&i32) = move _19;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          (_18.1: &&i32) = move _21;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_21);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_19);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _22 = (_18.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          _23 = (_18.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          StorageLive(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _25 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_11);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_12.0: &&i32) = &_13;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _14 = &_15;                      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_12.1: &&i32) = move _14;       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageDead(_14);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _20 = (_12.0: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _23 = (_12.1: &&i32);            // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          _19 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _28 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _25) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _18 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _19) -> bb3; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb3: {
-          StorageLive(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _29 = transmute::<&&i32, &core::fmt::Opaque>(move _22) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_16.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _20) -> bb4; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb4: {
-          (_24.0: &core::fmt::Opaque) = move _29; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_24.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _28; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_29);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_28);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageLive(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _27 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          (_16.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _18; // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _22 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer)); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {<&i32 as std::fmt::Debug>::fmt}, val: Value(Scalar(<ZST>)) }
-          StorageLive(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _30 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _27) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageLive(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _21 = transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>(move _22) -> bb5; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) -> for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> {std::intrinsics::transmute::<for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>, for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb5: {
-          StorageLive(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _31 = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_17.0: &core::fmt::Opaque) = transmute::<&&i32, &core::fmt::Opaque>(move _23) -> bb6; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/core/src/fmt/mod.rs:LL:COL
                                            // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&&i32) -> &core::fmt::Opaque {std::intrinsics::transmute::<&&i32, &core::fmt::Opaque>}, val: Value(Scalar(<ZST>)) }
       }
   
       bb6: {
-          (_26.0: &core::fmt::Opaque) = move _31; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_26.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _30; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_31);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_30);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _17 = [move _24, move _26];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_26);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageDead(_24);                // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _16 = &_17;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _15 = move _16 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          StorageLive(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          discriminant(_32) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.0: &[&str]) = move _14;     // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _32; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          (_13.2: &[std::fmt::ArgumentV1]) = move _15; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          StorageDead(_32);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
-          _12 = &_13;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          begin_panic_fmt(move _12);       // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          (_17.1: for<'r, 's, 't0> fn(&'r core::fmt::Opaque, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error>) = move _21; // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_21);                // scope 9 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _11 = [move _16, move _17];      // scope 5 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _10 = &_11;                      // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _25 = move _10 as &[std::fmt::ArgumentV1] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          StorageLive(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          discriminant(_24) = 0;           // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.1: std::option::Option<&[std::fmt::rt::v1::Argument]>) = move _24; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          (_9.2: &[std::fmt::ArgumentV1]) = move _25; // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          StorageDead(_24);                // scope 10 at $SRC_DIR/core/src/fmt/mod.rs:LL:COL
+          _8 = &_9;                        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          begin_panic_fmt(move _8);        // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'r, 's> fn(&'r std::fmt::Arguments<'s>) -> ! {std::rt::begin_panic_fmt}, val: Value(Scalar(<ZST>)) }
diff --git a/src/test/mir-opt/nrvo-simple.rs b/src/test/mir-opt/nrvo-simple.rs
index f0eb711b3f0..ab46d7b94c7 100644
--- a/src/test/mir-opt/nrvo-simple.rs
+++ b/src/test/mir-opt/nrvo-simple.rs
@@ -1,3 +1,5 @@
+// compile-flags: -Zmir-opt-level=1
+
 // EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
 fn nrvo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
     let mut buf = [0; 1024];
diff --git a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
index 924e87ea8c0..f438eaa0027 100644
--- a/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
+++ b/src/test/mir-opt/nrvo_simple.nrvo.RenameReturnPlace.diff
@@ -2,39 +2,42 @@
 + // MIR for `nrvo` after RenameReturnPlace
   
   fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] {
-      debug init => _1;                    // in scope 0 at $DIR/nrvo-simple.rs:2:9: 2:13
--     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:2:39: 2:49
-+     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:3:9: 3:16
-      let mut _2: [u8; 1024];              // in scope 0 at $DIR/nrvo-simple.rs:3:9: 3:16
-      let _3: ();                          // in scope 0 at $DIR/nrvo-simple.rs:4:5: 4:19
-      let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:4:5: 4:9
-      let mut _5: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:4:10: 4:18
-      let mut _6: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:4:10: 4:18
+      debug init => _1;                    // in scope 0 at $DIR/nrvo-simple.rs:4:9: 4:13
+-     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:4:39: 4:49
++     let mut _0: [u8; 1024];              // return place in scope 0 at $DIR/nrvo-simple.rs:5:9: 5:16
+      let mut _2: [u8; 1024];              // in scope 0 at $DIR/nrvo-simple.rs:5:9: 5:16
+      let _3: ();                          // in scope 0 at $DIR/nrvo-simple.rs:6:5: 6:19
+      let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/nrvo-simple.rs:6:5: 6:9
+      let mut _5: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:6:10: 6:18
+      let mut _6: &mut [u8; 1024];         // in scope 0 at $DIR/nrvo-simple.rs:6:10: 6:18
       scope 1 {
--         debug buf => _2;                 // in scope 1 at $DIR/nrvo-simple.rs:3:9: 3:16
-+         debug buf => _0;                 // in scope 1 at $DIR/nrvo-simple.rs:3:9: 3:16
+-         debug buf => _2;                 // in scope 1 at $DIR/nrvo-simple.rs:5:9: 5:16
++         debug buf => _0;                 // in scope 1 at $DIR/nrvo-simple.rs:5:9: 5:16
       }
   
       bb0: {
--         StorageLive(_2);                 // scope 0 at $DIR/nrvo-simple.rs:3:9: 3:16
--         _2 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:3:19: 3:28
-+         _0 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:3:19: 3:28
-          StorageLive(_3);                 // scope 1 at $DIR/nrvo-simple.rs:4:5: 4:19
-          StorageLive(_5);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-          StorageLive(_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
--         _6 = &mut _2;                    // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-+         _6 = &mut _0;                    // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-          _5 = &mut (*_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:10: 4:18
-          _3 = move _1(move _5) -> bb1;    // scope 1 at $DIR/nrvo-simple.rs:4:5: 4:19
+-         StorageLive(_2);                 // scope 0 at $DIR/nrvo-simple.rs:5:9: 5:16
+-         _2 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:5:19: 5:28
++         _0 = [const 0_u8; 1024];         // scope 0 at $DIR/nrvo-simple.rs:5:19: 5:28
+          StorageLive(_3);                 // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:19
+          StorageLive(_4);                 // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:9
+          _4 = _1;                         // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:9
+          StorageLive(_5);                 // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+          StorageLive(_6);                 // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+-         _6 = &mut _2;                    // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
++         _6 = &mut _0;                    // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+          _5 = &mut (*_6);                 // scope 1 at $DIR/nrvo-simple.rs:6:10: 6:18
+          _3 = move _4(move _5) -> bb1;    // scope 1 at $DIR/nrvo-simple.rs:6:5: 6:19
       }
   
       bb1: {
-          StorageDead(_5);                 // scope 1 at $DIR/nrvo-simple.rs:4:18: 4:19
-          StorageDead(_6);                 // scope 1 at $DIR/nrvo-simple.rs:4:19: 4:20
-          StorageDead(_3);                 // scope 1 at $DIR/nrvo-simple.rs:4:19: 4:20
--         _0 = _2;                         // scope 1 at $DIR/nrvo-simple.rs:5:5: 5:8
--         StorageDead(_2);                 // scope 0 at $DIR/nrvo-simple.rs:6:1: 6:2
-          return;                          // scope 0 at $DIR/nrvo-simple.rs:6:2: 6:2
+          StorageDead(_5);                 // scope 1 at $DIR/nrvo-simple.rs:6:18: 6:19
+          StorageDead(_4);                 // scope 1 at $DIR/nrvo-simple.rs:6:18: 6:19
+          StorageDead(_6);                 // scope 1 at $DIR/nrvo-simple.rs:6:19: 6:20
+          StorageDead(_3);                 // scope 1 at $DIR/nrvo-simple.rs:6:19: 6:20
+-         _0 = _2;                         // scope 1 at $DIR/nrvo-simple.rs:7:5: 7:8
+-         StorageDead(_2);                 // scope 0 at $DIR/nrvo-simple.rs:8:1: 8:2
+          return;                          // scope 0 at $DIR/nrvo-simple.rs:8:2: 8:2
       }
   }
   
diff --git a/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff b/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
new file mode 100644
index 00000000000..c3e503bf2c6
--- /dev/null
+++ b/src/test/mir-opt/rustc.try_identity.DestinationPropagation.diff
@@ -0,0 +1,72 @@
+- // MIR for `try_identity` before DestinationPropagation
++ // MIR for `try_identity` after DestinationPropagation
+  
+  fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
+      scope 1 {
+          debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
+      }
+      scope 2 {
+          debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
+          scope 3 {
+              scope 7 {
+                  debug t => _9;           // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL
+              }
+              scope 8 {
+                  debug v => _8;           // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
+              }
+          }
+      }
+      scope 4 {
+          debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
+          scope 5 {
+          }
+      }
+      scope 6 {
+-         debug self => _4;                // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
++         debug self => _0;                // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+-         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+-         _3 = move _4;                    // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
+-         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
++         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
++         nop;                             // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      }
+  
+      bb1: {
+-         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
++         nop;                             // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
+      }
+  
+      bb2: {
+          return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/simplify_try.rs b/src/test/mir-opt/simplify_try.rs
index fa127de13df..fca80bee896 100644
--- a/src/test/mir-opt/simplify_try.rs
+++ b/src/test/mir-opt/simplify_try.rs
@@ -1,6 +1,7 @@
 // EMIT_MIR simplify_try.try_identity.SimplifyArmIdentity.diff
 // EMIT_MIR simplify_try.try_identity.SimplifyBranchSame.after.mir
 // EMIT_MIR simplify_try.try_identity.SimplifyLocals.after.mir
+// EMIT_MIR simplify_try.try_identity.DestinationPropagation.diff
 
 fn try_identity(x: Result<u32, i32>) -> Result<u32, i32> {
     let y = x?;
diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
new file mode 100644
index 00000000000..187a3cfbb89
--- /dev/null
+++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
@@ -0,0 +1,72 @@
+- // MIR for `try_identity` before DestinationPropagation
++ // MIR for `try_identity` after DestinationPropagation
+  
+  fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
+      scope 1 {
+          debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
+      }
+      scope 2 {
+          debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
+          scope 3 {
+              scope 7 {
+                  debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+              }
+              scope 8 {
+                  debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
+              }
+          }
+      }
+      scope 4 {
+          debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
+          scope 5 {
+          }
+      }
+      scope 6 {
+-         debug self => _4;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         debug self => _0;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+      }
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+-         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+-         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+-         _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+-         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
++         _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
++         nop;                             // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         _5 = discriminant(_0);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      }
+  
+      bb1: {
+-         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
++         nop;                             // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
++         nop;                             // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
+      }
+  
+      bb2: {
+          return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
index 26ce290b549..0c687684c50 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
@@ -2,25 +2,25 @@
 + // MIR for `try_identity` after SimplifyArmIdentity
   
   fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
-      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+      debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+      let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+      let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+      let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+      let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+      let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+      let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
       scope 1 {
--         debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
-+         debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+-         debug y => _2;                   // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
++         debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
       }
       scope 2 {
--         debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
-+         debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+-         debug err => _6;                 // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
++         debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
           scope 3 {
               scope 7 {
 -                 debug t => _9;           // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
@@ -29,13 +29,13 @@
               scope 8 {
 -                 debug v => _8;           // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+                  let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
               }
           }
       }
       scope 4 {
--         debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
-+         debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+-         debug val => _10;                // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
++         debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
           scope 5 {
           }
       }
@@ -44,55 +44,55 @@
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-          StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-          StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-          _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+          StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+          StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+          StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+          _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
           _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+          StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
       }
   
       bb1: {
--         StorageLive(_10);                // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
--         _10 = ((_3 as Ok).0: u32);       // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
--         _2 = _10;                        // scope 5 at $DIR/simplify_try.rs:6:13: 6:15
--         StorageDead(_10);                // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-+         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
-          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
--         StorageLive(_11);                // scope 1 at $DIR/simplify_try.rs:7:8: 7:9
--         _11 = _2;                        // scope 1 at $DIR/simplify_try.rs:7:8: 7:9
--         ((_0 as Ok).0: u32) = move _11;  // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
--         discriminant(_0) = 0;            // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
--         StorageDead(_11);                // scope 1 at $DIR/simplify_try.rs:7:9: 7:10
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+-         StorageLive(_10);                // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         _10 = ((_3 as Ok).0: u32);       // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+-         _2 = _10;                        // scope 5 at $DIR/simplify_try.rs:7:13: 7:15
+-         StorageDead(_10);                // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
++         _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+-         StorageLive(_11);                // scope 1 at $DIR/simplify_try.rs:8:8: 8:9
+-         _11 = _2;                        // scope 1 at $DIR/simplify_try.rs:8:8: 8:9
+-         ((_0 as Ok).0: u32) = move _11;  // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         discriminant(_0) = 0;            // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+-         StorageDead(_11);                // scope 1 at $DIR/simplify_try.rs:8:9: 8:10
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   
       bb2: {
--         StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
--         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
--         StorageLive(_8);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
--         StorageLive(_9);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
--         _9 = _6;                         // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
+-         StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+-         StorageLive(_8);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
+-         StorageLive(_9);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
+-         _9 = _6;                         // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
 -         _8 = move _9;                    // scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
--         StorageDead(_9);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
+-         StorageDead(_9);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
 -         StorageLive(_12);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         _12 = move _8;                   // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         ((_0 as Err).0: i32) = move _12; // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         discriminant(_0) = 1;            // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 -         StorageDead(_12);                // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
--         StorageDead(_8);                 // scope 3 at $DIR/simplify_try.rs:6:14: 6:15
--         StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+-         StorageDead(_8);                 // scope 3 at $DIR/simplify_try.rs:7:14: 7:15
+-         StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
 +         _0 = move _3;                    // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+          StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+          StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+          goto -> bb3;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
       }
   
       bb3: {
-          return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+          return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
       }
   }
   
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
index dc4aae176f2..9428d305c87 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
@@ -1,35 +1,35 @@
 // MIR for `try_identity` after SimplifyBranchSame
 
 fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
-    let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-    let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-    let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-    let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-    let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-    let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9
+    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
+    let _2: u32;                         // in scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+    let mut _3: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+    let mut _4: std::result::Result<u32, i32>; // in scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+    let mut _5: isize;                   // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let _6: i32;                         // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let mut _7: !;                       // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let mut _8: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let mut _9: i32;                     // in scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+    let _10: u32;                        // in scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+    let mut _11: u32;                    // in scope 0 at $DIR/simplify_try.rs:8:8: 8:9
     scope 1 {
-        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
     }
     scope 2 {
-        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
         scope 3 {
             scope 7 {
                 debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
             }
             scope 8 {
                 debug v => ((_0 as Err).0: i32); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15
+                let mut _12: i32;        // in scope 8 at $DIR/simplify_try.rs:7:14: 7:15
             }
         }
     }
     scope 4 {
-        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
         scope 5 {
         }
     }
@@ -38,24 +38,24 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:6:9: 6:10
-        StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:15
-        StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
-        _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:6:13: 6:14
+        StorageLive(_2);                 // scope 0 at $DIR/simplify_try.rs:7:9: 7:10
+        StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:15
+        StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+        _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
         _3 = move _4;                    // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-        StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
-        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:6:14: 6:15
+        StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+        _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
+        goto -> bb1;                     // scope 0 at $DIR/simplify_try.rs:7:14: 7:15
     }
 
     bb1: {
-        _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
-        StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:6:15: 6:16
-        StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:8:1: 8:2
-        goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+        _0 = move _3;                    // scope 1 at $DIR/simplify_try.rs:8:5: 8:10
+        StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:7:15: 7:16
+        StorageDead(_2);                 // scope 0 at $DIR/simplify_try.rs:9:1: 9:2
+        goto -> bb2;                     // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
     }
 
     bb2: {
-        return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+        return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
     }
 }
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
index d65a2b12c0f..a25472f6a5e 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
@@ -1,13 +1,13 @@
 // MIR for `try_identity` after SimplifyLocals
 
 fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i32> {
-    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18
-    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57
+    debug x => _1;                       // in scope 0 at $DIR/simplify_try.rs:6:17: 6:18
+    let mut _0: std::result::Result<u32, i32>; // return place in scope 0 at $DIR/simplify_try.rs:6:41: 6:57
     scope 1 {
-        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10
+        debug y => ((_0 as Ok).0: u32);  // in scope 1 at $DIR/simplify_try.rs:7:9: 7:10
     }
     scope 2 {
-        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15
+        debug err => ((_0 as Err).0: i32); // in scope 2 at $DIR/simplify_try.rs:7:14: 7:15
         scope 3 {
             scope 7 {
                 debug t => ((_0 as Err).0: i32); // in scope 7 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
@@ -18,16 +18,16 @@ fn try_identity(_1: std::result::Result<u32, i32>) -> std::result::Result<u32, i
         }
     }
     scope 4 {
-        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15
+        debug val => ((_0 as Ok).0: u32); // in scope 4 at $DIR/simplify_try.rs:7:13: 7:15
         scope 5 {
         }
     }
     scope 6 {
-        debug self => _1;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+        debug self => _0;                // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb0: {
-        _0 = move _1;                    // scope 1 at $DIR/simplify_try.rs:7:5: 7:10
-        return;                          // scope 0 at $DIR/simplify_try.rs:8:2: 8:2
+        _0 = _1;                         // scope 0 at $DIR/simplify_try.rs:7:13: 7:14
+        return;                          // scope 0 at $DIR/simplify_try.rs:9:2: 9:2
     }
 }
diff --git a/src/test/ui/dest-prop/skeptic-miscompile.rs b/src/test/ui/dest-prop/skeptic-miscompile.rs
new file mode 100644
index 00000000000..c27a1f04532
--- /dev/null
+++ b/src/test/ui/dest-prop/skeptic-miscompile.rs
@@ -0,0 +1,24 @@
+// run-pass
+
+// compile-flags: -Zmir-opt-level=2
+
+trait IterExt: Iterator {
+    fn fold_ex<B, F>(mut self, init: B, mut f: F) -> B
+    where
+        Self: Sized,
+        F: FnMut(B, Self::Item) -> B,
+    {
+        let mut accum = init;
+        while let Some(x) = self.next() {
+            accum = f(accum, x);
+        }
+        accum
+    }
+}
+
+impl<T: Iterator> IterExt for T {}
+
+fn main() {
+    let test = &["\n"];
+    test.iter().fold_ex(String::new(), |_, b| b.to_string());
+}