about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2022-12-04 18:26:09 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-05-09 17:59:34 +0000
commit34903755701a5595ee4bab3bb89de15c5469cd3e (patch)
tree86d662115d239932ad2f5f5ebddf431be78ce84a
parentf7b831ac8a897273f78b9f47165cf8e54066ce4b (diff)
downloadrust-34903755701a5595ee4bab3bb89de15c5469cd3e.tar.gz
rust-34903755701a5595ee4bab3bb89de15c5469cd3e.zip
Implement SSA-based reference propagation.
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs13
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs66
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs2
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs2
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs2
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs324
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs130
-rw-r--r--tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff38
-rw-r--r--tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff50
-rw-r--r--tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff27
-rw-r--r--tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff24
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff292
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff334
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff288
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff294
-rw-r--r--tests/mir-opt/reference_prop.rs428
-rw-r--r--tests/mir-opt/slice_filter.rs2
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff88
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff239
-rw-r--r--tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff103
21 files changed, 2668 insertions, 80 deletions
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index f2841182a1a..55991facd89 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1524,6 +1524,19 @@ impl<V, T> ProjectionElem<V, T> {
         }
     }
 
+    /// Returns `true` if the target of this projection always refers to the same memory region
+    /// whatever the state of the program.
+    pub fn is_stable_offset(&self) -> bool {
+        match self {
+            Self::Deref | Self::Index(_) => false,
+            Self::Field(_, _)
+            | Self::OpaqueCast(_)
+            | Self::ConstantIndex { .. }
+            | Self::Subslice { .. }
+            | Self::Downcast(_, _) => true,
+        }
+    }
+
     /// Returns `true` if this is a `Downcast` projection with the given `VariantIdx`.
     pub fn is_downcast_to(&self, v: VariantIdx) -> bool {
         matches!(*self, Self::Downcast(_, x) if x == v)
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index 2a0aff55083..171db6965ac 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -26,7 +26,7 @@ pub use self::borrowed_locals::borrowed_locals;
 pub use self::borrowed_locals::MaybeBorrowedLocals;
 pub use self::liveness::MaybeLiveLocals;
 pub use self::liveness::MaybeTransitiveLiveLocals;
-pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageLive};
+pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive};
 
 /// `MaybeInitializedPlaces` tracks all places that might be
 /// initialized upon reaching a particular point in the control flow
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 4a5d9d52010..9656148581f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -74,6 +74,72 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
     }
 }
 
+#[derive(Clone)]
+pub struct MaybeStorageDead {
+    always_live_locals: BitSet<Local>,
+}
+
+impl MaybeStorageDead {
+    pub fn new(always_live_locals: BitSet<Local>) -> Self {
+        MaybeStorageDead { always_live_locals }
+    }
+}
+
+impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead {
+    type Domain = BitSet<Local>;
+
+    const NAME: &'static str = "maybe_storage_dead";
+
+    fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
+        // bottom = live
+        BitSet::new_empty(body.local_decls.len())
+    }
+
+    fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut Self::Domain) {
+        assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size());
+        for local in body.vars_and_temps_iter() {
+            if !self.always_live_locals.contains(local) {
+                on_entry.insert(local);
+            }
+        }
+    }
+}
+
+impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
+    type Idx = Local;
+
+    fn statement_effect(
+        &self,
+        trans: &mut impl GenKill<Self::Idx>,
+        stmt: &mir::Statement<'tcx>,
+        _: Location,
+    ) {
+        match stmt.kind {
+            StatementKind::StorageLive(l) => trans.kill(l),
+            StatementKind::StorageDead(l) => trans.gen(l),
+            _ => (),
+        }
+    }
+
+    fn terminator_effect(
+        &self,
+        _trans: &mut impl GenKill<Self::Idx>,
+        _: &mir::Terminator<'tcx>,
+        _: Location,
+    ) {
+        // Terminators have no effect
+    }
+
+    fn call_return_effect(
+        &self,
+        _trans: &mut impl GenKill<Self::Idx>,
+        _block: BasicBlock,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
+    ) {
+        // Nothing to do when a call returns successfully
+    }
+}
+
 type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>;
 
 /// Dataflow analysis that determines whether each local requires storage at a
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 3922ed2fbf7..2fa5c0bca15 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -76,7 +76,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
 fn fully_moved_locals(ssa: &SsaLocals, body: &Body<'_>) -> BitSet<Local> {
     let mut fully_moved = BitSet::new_filled(body.local_decls.len());
 
-    for (_, rvalue) in ssa.assignments(body) {
+    for (_, rvalue, _) in ssa.assignments(body) {
         let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) | Rvalue::CopyForDeref(place))
             = rvalue
         else { continue };
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 5c4b1ead4e9..277237a5515 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -84,6 +84,7 @@ mod match_branches;
 mod multiple_return_terminators;
 mod normalize_array_len;
 mod nrvo;
+mod ref_prop;
 mod remove_noop_landing_pads;
 mod remove_storage_markers;
 mod remove_uninit_drops;
@@ -559,6 +560,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             &separate_const_switch::SeparateConstSwitch,
             &simplify::SimplifyLocals::BeforeConstProp,
             &copy_prop::CopyProp,
+            &ref_prop::ReferencePropagation,
             &const_prop::ConstProp,
             &dataflow_const_prop::DataflowConstProp,
             //
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index b3b831bb4ab..109a2c0aec6 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -41,7 +41,7 @@ fn compute_slice_length<'tcx>(
 ) -> IndexVec<Local, Option<ty::Const<'tcx>>> {
     let mut slice_lengths = IndexVec::from_elem(None, &body.local_decls);
 
-    for (local, rvalue) in ssa.assignments(body) {
+    for (local, rvalue, _) in ssa.assignments(body) {
         match rvalue {
             Rvalue::Cast(
                 CastKind::Pointer(ty::adjustment::PointerCast::Unsize),
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
new file mode 100644
index 00000000000..dfdf4caf881
--- /dev/null
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -0,0 +1,324 @@
+use rustc_data_structures::fx::FxHashSet;
+use rustc_index::bit_set::BitSet;
+use rustc_index::IndexVec;
+use rustc_middle::mir::visit::*;
+use rustc_middle::mir::*;
+use rustc_middle::ty::TyCtxt;
+use rustc_mir_dataflow::impls::{borrowed_locals, MaybeStorageDead};
+use rustc_mir_dataflow::storage::always_storage_live_locals;
+use rustc_mir_dataflow::Analysis;
+
+use crate::ssa::SsaLocals;
+use crate::MirPass;
+
+/// Propagate references using SSA analysis.
+///
+/// MIR building may produce a lot of borrow-dereference patterns.
+///
+/// This pass aims to transform the following pattern:
+///   _1 = &raw? mut? PLACE;
+///   _3 = *_1;
+///   _4 = &raw? mut? *_1;
+///
+/// Into
+///   _1 = &raw? mut? PLACE;
+///   _3 = PLACE;
+///   _4 = &raw? mut? PLACE;
+///
+/// where `PLACE` is a direct or an indirect place expression.
+///
+/// There are 3 properties that need to be upheld for this transformation to be legal:
+/// - place stability: `PLACE` must refer to the same memory wherever it appears;
+/// - pointer liveness: we must not introduce dereferences of dangling pointers;
+/// - `&mut` borrow uniqueness.
+///
+/// # Stability
+///
+/// If `PLACE` is an indirect projection, if its of the form `(*LOCAL).PROJECTIONS` where:
+/// - `LOCAL` is SSA;
+/// - all projections in `PROJECTIONS` have a stable offset (no dereference and no indexing).
+///
+/// If `PLACE` is a direct projection of a local, we consider it as constant if:
+/// - the local is always live, or it has a single `StorageLive` that dominates all uses;
+/// - all projections have a stable offset.
+///
+/// # Liveness
+///
+/// When performing a substitution, we must take care not to introduce uses of dangling locals.
+/// To ensure this, we walk the body with the `MaybeStorageDead` dataflow analysis:
+/// - if we want to replace `*x` by reborrow `*y` and `y` may be dead, we allow replacement and
+///   mark storage statements on `y` for removal;
+/// - if we want to replace `*x` by non-reborrow `y` and `y` must be live, we allow replacement;
+/// - if we want to replace `*x` by non-reborrow `y` and `y` may be dead, we do not replace.
+///
+/// # Uniqueness
+///
+/// For `&mut` borrows, we also need to preserve the uniqueness property:
+/// we must avoid creating a state where we interleave uses of `*_1` and `_2`.
+/// To do it, we only perform full substitution of mutable borrows:
+/// we replace either all or none of the occurrences of `*_1`.
+///
+/// Some care has to be taken when `_1` is copied in other locals.
+///   _1 = &raw? mut? _2;
+///   _3 = *_1;
+///   _4 = _1
+///   _5 = *_4
+/// In such cases, fully substituting `_1` means fully substituting all of the copies.
+///
+/// For immutable borrows, we do not need to preserve such uniqueness property,
+/// so we perform all the possible substitutions without removing the `_1 = &_2` statement.
+pub struct ReferencePropagation;
+
+impl<'tcx> MirPass<'tcx> for ReferencePropagation {
+    fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
+        sess.mir_opt_level() >= 4
+    }
+
+    #[instrument(level = "trace", skip(self, tcx, body))]
+    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+        debug!(def_id = ?body.source.def_id());
+        propagate_ssa(tcx, body);
+    }
+}
+
+fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+    let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+    let borrowed_locals = borrowed_locals(body);
+    let ssa = SsaLocals::new(tcx, param_env, body, &borrowed_locals);
+
+    let mut replacer = compute_replacement(tcx, body, &ssa);
+    debug!(?replacer.targets, ?replacer.allowed_replacements, ?replacer.storage_to_remove);
+
+    replacer.visit_body_preserves_cfg(body);
+
+    if replacer.any_replacement {
+        crate::simplify::remove_unused_definitions(body);
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum Value<'tcx> {
+    /// Not a pointer, or we can't know.
+    Unknown,
+    /// We know the value to be a pointer to this place.
+    /// The boolean indicates whether the reference is mutable, subject the uniqueness rule.
+    Pointer(Place<'tcx>, bool),
+}
+
+/// For each local, save the place corresponding to `*local`.
+#[instrument(level = "trace", skip(tcx, body))]
+fn compute_replacement<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &Body<'tcx>,
+    ssa: &SsaLocals,
+) -> Replacer<'tcx> {
+    // Compute `MaybeStorageDead` dataflow to check that we only replace when the pointee is
+    // definitely live.
+    let always_live_locals = always_storage_live_locals(body);
+    let mut maybe_dead = MaybeStorageDead::new(always_live_locals)
+        .into_engine(tcx, body)
+        .iterate_to_fixpoint()
+        .into_results_cursor(body);
+
+    // Map for each local to the pointee.
+    let mut targets = IndexVec::from_elem(Value::Unknown, &body.local_decls);
+    // Set of locals for which we will remove their storage statement. This is useful for
+    // reborrowed references.
+    let mut storage_to_remove = BitSet::new_empty(body.local_decls.len());
+
+    let fully_replacable_locals = fully_replacable_locals(ssa);
+
+    let mut can_perform_opt = |target: Place<'tcx>, loc: Location| {
+        maybe_dead.seek_after_primary_effect(loc);
+        let maybe_dead = maybe_dead.contains(target.local);
+
+        if target.projection.first() == Some(&PlaceElem::Deref) {
+            // We are creating a reborrow. As `place.local` is a reference, removing the
+            // `StorageDead` is fine.
+            if maybe_dead {
+                storage_to_remove.insert(target.local);
+            }
+            true
+        } else {
+            // This is a proper dereference. We can only allow it if `target` is live.
+            !maybe_dead
+        }
+    };
+
+    for (local, rvalue, location) in ssa.assignments(body) {
+        debug!(?local);
+
+        // Only visit if we have something to do.
+        let Value::Unknown = targets[local] else { bug!() };
+
+        let ty = body.local_decls[local].ty;
+
+        // If this is not a reference or pointer, do nothing.
+        if !ty.is_any_ptr() {
+            debug!("not a reference or pointer");
+            continue;
+        }
+
+        // If this a mutable reference that we cannot fully replace, mark it as unknown.
+        if ty.is_mutable_ptr() && !fully_replacable_locals.contains(local) {
+            debug!("not fully replaceable");
+            continue;
+        }
+
+        debug!(?rvalue);
+        match rvalue {
+            // This is a copy, just use the value we have in store for the previous one.
+            // As we are visiting in `assignment_order`, ie. reverse postorder, `rhs` should
+            // have been visited before.
+            Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
+            | Rvalue::CopyForDeref(place) => {
+                if let Some(rhs) = place.as_local() {
+                    let target = targets[rhs];
+                    if matches!(target, Value::Pointer(..)) {
+                        targets[local] = target;
+                    } else if ssa.is_ssa(rhs) {
+                        let refmut = body.local_decls[rhs].ty.is_mutable_ptr();
+                        targets[local] = Value::Pointer(tcx.mk_place_deref(rhs.into()), refmut);
+                    }
+                }
+            }
+            Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
+                let mut place = *place;
+                // Try to see through `place` in order to collapse reborrow chains.
+                if place.projection.first() == Some(&PlaceElem::Deref)
+                    && let Value::Pointer(target, refmut) = targets[place.local]
+                    // Only see through immutable reference and pointers, as we do not know yet if
+                    // mutable references are fully replaced.
+                    && !refmut
+                    // Only collapse chain if the pointee is definitely live.
+                    && can_perform_opt(target, location)
+                {
+                    place = target.project_deeper(&place.projection[1..], tcx);
+                }
+                assert_ne!(place.local, local);
+                if ssa.is_constant_place(place) {
+                    targets[local] = Value::Pointer(place, ty.is_mutable_ptr());
+                }
+            }
+            // We do not know what to do, so keep as not-a-pointer.
+            _ => {}
+        }
+    }
+
+    debug!(?targets);
+
+    let mut finder = ReplacementFinder {
+        targets: &mut targets,
+        can_perform_opt,
+        allowed_replacements: FxHashSet::default(),
+    };
+    let reachable_blocks = traversal::reachable_as_bitset(body);
+    for (bb, bbdata) in body.basic_blocks.iter_enumerated() {
+        // Only visit reachable blocks as we rely on dataflow.
+        if reachable_blocks.contains(bb) {
+            finder.visit_basic_block_data(bb, bbdata);
+        }
+    }
+
+    let allowed_replacements = finder.allowed_replacements;
+    return Replacer {
+        tcx,
+        targets,
+        storage_to_remove,
+        allowed_replacements,
+        any_replacement: false,
+    };
+
+    struct ReplacementFinder<'a, 'tcx, F> {
+        targets: &'a mut IndexVec<Local, Value<'tcx>>,
+        can_perform_opt: F,
+        allowed_replacements: FxHashSet<(Local, Location)>,
+    }
+
+    impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'_, 'tcx, F>
+    where
+        F: FnMut(Place<'tcx>, Location) -> bool,
+    {
+        fn visit_place(&mut self, place: &Place<'tcx>, ctxt: PlaceContext, loc: Location) {
+            if matches!(ctxt, PlaceContext::NonUse(_)) {
+                // There is no need to check liveness for non-uses.
+                return;
+            }
+
+            if let Value::Pointer(target, refmut) = self.targets[place.local]
+                && place.projection.first() == Some(&PlaceElem::Deref)
+            {
+                let perform_opt = (self.can_perform_opt)(target, loc);
+                if perform_opt {
+                    self.allowed_replacements.insert((target.local, loc));
+                } else if refmut {
+                    // This mutable reference is not fully replacable, so drop it.
+                    self.targets[place.local] = Value::Unknown;
+                }
+            }
+        }
+    }
+}
+
+/// Compute the set of locals that can be fully replaced.
+///
+/// We consider a local to be replacable iff it's only used in a `Deref` projection `*_local` or
+/// non-use position (like storage statements and debuginfo).
+fn fully_replacable_locals(ssa: &SsaLocals) -> BitSet<Local> {
+    let mut replacable = BitSet::new_empty(ssa.num_locals());
+
+    // First pass: for each local, whether its uses can be fully replaced.
+    for local in ssa.locals() {
+        if ssa.num_direct_uses(local) == 0 {
+            replacable.insert(local);
+        }
+    }
+
+    // Second pass: a local can only be fully replaced if all its copies can.
+    ssa.meet_copy_equivalence(&mut replacable);
+
+    replacable
+}
+
+/// Utility to help performing subtitution of `*pattern` by `target`.
+struct Replacer<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    targets: IndexVec<Local, Value<'tcx>>,
+    storage_to_remove: BitSet<Local>,
+    allowed_replacements: FxHashSet<(Local, Location)>,
+    any_replacement: bool,
+}
+
+impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
+        if let Value::Pointer(target, _) = self.targets[place.local]
+            && place.projection.first() == Some(&PlaceElem::Deref)
+        {
+            let perform_opt = matches!(ctxt, PlaceContext::NonUse(_))
+                || self.allowed_replacements.contains(&(target.local, loc));
+
+            if perform_opt {
+                *place = target.project_deeper(&place.projection[1..], self.tcx);
+                self.any_replacement = true;
+            }
+        } else {
+            self.super_place(place, ctxt, loc);
+        }
+    }
+
+    fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) {
+        match stmt.kind {
+            StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
+                if self.storage_to_remove.contains(l) =>
+            {
+                stmt.make_nop();
+            }
+            // Do not remove assignments as they may still be useful for debuginfo.
+            _ => self.super_statement(stmt, loc),
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index ec8d42c1652..270bb540b80 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -6,6 +6,7 @@ use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{ParamEnv, TyCtxt};
+use rustc_mir_dataflow::storage::always_storage_live_locals;
 
 #[derive(Debug)]
 pub struct SsaLocals {
@@ -17,6 +18,12 @@ pub struct SsaLocals {
     assignment_order: Vec<Local>,
     /// Copy equivalence classes between locals. See `copy_classes` for documentation.
     copy_classes: IndexVec<Local, Local>,
+    /// Number of "direct" uses of each local, ie. uses that are not dereferences.
+    /// We ignore non-uses (Storage statements, debuginfo).
+    direct_uses: IndexVec<Local, u32>,
+    /// Set of "StorageLive" statements for each local. When the "StorageLive" statement does not
+    /// dominate all uses of the local, we mark it as `Set1::Many`.
+    storage_live: IndexVec<Local, Set1<LocationExtended>>,
 }
 
 /// We often encounter MIR bodies with 1 or 2 basic blocks. In those cases, it's unnecessary to
@@ -26,23 +33,31 @@ struct SmallDominators {
     inner: Option<Dominators<BasicBlock>>,
 }
 
-trait DomExt {
-    fn dominates(self, _other: Self, dominators: &SmallDominators) -> bool;
-}
-
-impl DomExt for Location {
-    fn dominates(self, other: Location, dominators: &SmallDominators) -> bool {
-        if self.block == other.block {
-            self.statement_index <= other.statement_index
+impl SmallDominators {
+    fn dominates(&self, first: Location, second: Location) -> bool {
+        if first.block == second.block {
+            first.statement_index <= second.statement_index
+        } else if let Some(inner) = &self.inner {
+            inner.dominates(first.block, second.block)
         } else {
-            dominators.dominates(self.block, other.block)
+            first.block < second.block
         }
     }
-}
 
-impl SmallDominators {
-    fn dominates(&self, dom: BasicBlock, node: BasicBlock) -> bool {
-        if let Some(inner) = &self.inner { inner.dominates(dom, node) } else { dom < node }
+    fn check_dominates(&mut self, set: &mut Set1<LocationExtended>, loc: Location) {
+        let assign_dominates = match *set {
+            Set1::Empty | Set1::Many => false,
+            Set1::One(LocationExtended::Arg) => true,
+            Set1::One(LocationExtended::Plain(assign)) => {
+                self.dominates(assign.successor_within_block(), loc)
+            }
+        };
+        // We are visiting a use that is not dominated by an assignment.
+        // Either there is a cycle involved, or we are reading for uninitialized local.
+        // Bail out.
+        if !assign_dominates {
+            *set = Set1::Many;
+        }
     }
 }
 
@@ -59,7 +74,11 @@ impl SsaLocals {
         let dominators =
             if body.basic_blocks.len() > 2 { Some(body.basic_blocks.dominators()) } else { None };
         let dominators = SmallDominators { inner: dominators };
-        let mut visitor = SsaVisitor { assignments, assignment_order, dominators };
+
+        let direct_uses = IndexVec::from_elem(0, &body.local_decls);
+        let storage_live = IndexVec::from_elem(Set1::Empty, &body.local_decls);
+        let mut visitor =
+            SsaVisitor { assignments, assignment_order, dominators, direct_uses, storage_live };
 
         for (local, decl) in body.local_decls.iter_enumerated() {
             if matches!(body.local_kind(local), LocalKind::Arg) {
@@ -70,6 +89,10 @@ impl SsaLocals {
             }
         }
 
+        for local in always_storage_live_locals(body).iter() {
+            visitor.storage_live[local] = Set1::One(LocationExtended::Arg);
+        }
+
         if body.basic_blocks.len() > 2 {
             for (bb, data) in traversal::reverse_postorder(body) {
                 visitor.visit_basic_block_data(bb, data);
@@ -85,36 +108,66 @@ impl SsaLocals {
         }
 
         debug!(?visitor.assignments);
+        debug!(?visitor.direct_uses);
+        debug!(?visitor.storage_live);
 
         visitor
             .assignment_order
             .retain(|&local| matches!(visitor.assignments[local], Set1::One(_)));
         debug!(?visitor.assignment_order);
 
-        let copy_classes = compute_copy_classes(&visitor, body);
+        let copy_classes = compute_copy_classes(&mut visitor, body);
 
         SsaLocals {
             assignments: visitor.assignments,
             assignment_order: visitor.assignment_order,
+            direct_uses: visitor.direct_uses,
+            storage_live: visitor.storage_live,
             copy_classes,
         }
     }
 
+    pub fn num_locals(&self) -> usize {
+        self.assignments.len()
+    }
+
+    pub fn locals(&self) -> impl Iterator<Item = Local> {
+        self.assignments.indices()
+    }
+
     pub fn is_ssa(&self, local: Local) -> bool {
         matches!(self.assignments[local], Set1::One(_))
     }
 
+    /// Returns true iff we can use `p` as a pointee.
+    pub fn is_constant_place(&self, p: Place<'_>) -> bool {
+        // We only allow `Deref` as the first projection, to avoid surprises.
+        if p.projection.first() == Some(&PlaceElem::Deref) {
+            // `p == (*some_local).xxx`, it is constant only if `some_local` is constant.
+            // We approximate constness using SSAness.
+            self.is_ssa(p.local) && p.projection[1..].iter().all(PlaceElem::is_stable_offset)
+        } else {
+            matches!(self.storage_live[p.local], Set1::One(_))
+                && p.projection[..].iter().all(PlaceElem::is_stable_offset)
+        }
+    }
+
+    /// Return the number of uses if a local that are not "Deref".
+    pub fn num_direct_uses(&self, local: Local) -> u32 {
+        self.direct_uses[local]
+    }
+
     pub fn assignments<'a, 'tcx>(
         &'a self,
         body: &'a Body<'tcx>,
-    ) -> impl Iterator<Item = (Local, &'a Rvalue<'tcx>)> + 'a {
+    ) -> impl Iterator<Item = (Local, &'a Rvalue<'tcx>, Location)> + 'a {
         self.assignment_order.iter().filter_map(|&local| {
             if let Set1::One(LocationExtended::Plain(loc)) = self.assignments[local] {
                 // `loc` must point to a direct assignment to `local`.
                 let Either::Left(stmt) = body.stmt_at(loc) else { bug!() };
                 let Some((target, rvalue)) = stmt.kind.as_assign() else { bug!() };
                 assert_eq!(target.as_local(), Some(local));
-                Some((local, rvalue))
+                Some((local, rvalue, loc))
             } else {
                 None
             }
@@ -177,25 +230,8 @@ struct SsaVisitor {
     dominators: SmallDominators,
     assignments: IndexVec<Local, Set1<LocationExtended>>,
     assignment_order: Vec<Local>,
-}
-
-impl SsaVisitor {
-    fn check_assignment_dominates(&mut self, local: Local, loc: Location) {
-        let set = &mut self.assignments[local];
-        let assign_dominates = match *set {
-            Set1::Empty | Set1::Many => false,
-            Set1::One(LocationExtended::Arg) => true,
-            Set1::One(LocationExtended::Plain(assign)) => {
-                assign.successor_within_block().dominates(loc, &self.dominators)
-            }
-        };
-        // We are visiting a use that is not dominated by an assignment.
-        // Either there is a cycle involved, or we are reading for uninitialized local.
-        // Bail out.
-        if !assign_dominates {
-            *set = Set1::Many;
-        }
-    }
+    direct_uses: IndexVec<Local, u32>,
+    storage_live: IndexVec<Local, Set1<LocationExtended>>,
 }
 
 impl<'tcx> Visitor<'tcx> for SsaVisitor {
@@ -207,14 +243,23 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
                     // Only record if SSA-like, to avoid growing the vector needlessly.
                     self.assignment_order.push(local);
                 }
+                self.dominators.check_dominates(&mut self.storage_live[local], loc);
             }
             // Anything can happen with raw pointers, so remove them.
             PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
-            | PlaceContext::MutatingUse(_) => self.assignments[local] = Set1::Many,
+            | PlaceContext::MutatingUse(_) => {
+                self.assignments[local] = Set1::Many;
+                self.dominators.check_dominates(&mut self.storage_live[local], loc);
+            }
             // Immutable borrows are taken into account in `SsaLocals::new` by
             // removing non-freeze locals.
             PlaceContext::NonMutatingUse(_) => {
-                self.check_assignment_dominates(local, loc);
+                self.dominators.check_dominates(&mut self.assignments[local], loc);
+                self.dominators.check_dominates(&mut self.storage_live[local], loc);
+                self.direct_uses[local] += 1;
+            }
+            PlaceContext::NonUse(NonUseContext::StorageLive) => {
+                self.storage_live[local].insert(LocationExtended::Plain(loc));
             }
             PlaceContext::NonUse(_) => {}
         }
@@ -224,11 +269,12 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
         if place.projection.first() == Some(&PlaceElem::Deref) {
             // Do not do anything for storage statements and debuginfo.
             if ctxt.is_use() {
-                // A use through a `deref` only reads from the local, and cannot write to it.
+                // Only change the context if it is a real use, not a "use" in debuginfo.
                 let new_ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection);
 
                 self.visit_projection(place.as_ref(), new_ctxt, loc);
-                self.check_assignment_dominates(place.local, loc);
+                self.dominators.check_dominates(&mut self.assignments[place.local], loc);
+                self.dominators.check_dominates(&mut self.storage_live[place.local], loc);
             }
             return;
         }
@@ -237,7 +283,7 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor {
 }
 
 #[instrument(level = "trace", skip(ssa, body))]
-fn compute_copy_classes(ssa: &SsaVisitor, body: &Body<'_>) -> IndexVec<Local, Local> {
+fn compute_copy_classes(ssa: &mut SsaVisitor, body: &Body<'_>) -> IndexVec<Local, Local> {
     let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len());
 
     for &local in &ssa.assignment_order {
@@ -267,9 +313,11 @@ fn compute_copy_classes(ssa: &SsaVisitor, body: &Body<'_>) -> IndexVec<Local, Lo
         // We visit in `assignment_order`, ie. reverse post-order, so `rhs` has been
         // visited before `local`, and we just have to copy the representing local.
         copies[local] = copies[rhs];
+        ssa.direct_uses[rhs] -= 1;
     }
 
     debug!(?copies);
+    debug!(?ssa.direct_uses);
 
     // Invariant: `copies` must point to the head of an equivalence class.
     #[cfg(debug_assertions)]
diff --git a/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
new file mode 100644
index 00000000000..7e79e15ccda
--- /dev/null
+++ b/tests/mir-opt/reference_prop.dominate_storage.ReferencePropagation.diff
@@ -0,0 +1,38 @@
+- // MIR for `dominate_storage` before ReferencePropagation
++ // MIR for `dominate_storage` after ReferencePropagation
+  
+  fn dominate_storage() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:23: +0:23
+      let mut _1: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _2: &i32;                    // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _3: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _4: bool;                    // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _5: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _6: bool;                    // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+  
+      bb0: {
+          goto -> bb1;                     // scope 0 at $DIR/reference_prop.rs:+8:11: +8:20
+      }
+  
+      bb1: {
+          _1 = const 5_i32;                // scope 0 at $DIR/reference_prop.rs:+10:13: +10:18
+          _2 = &_1;                        // scope 0 at $DIR/reference_prop.rs:+11:13: +11:19
+          goto -> bb2;                     // scope 0 at $DIR/reference_prop.rs:+12:13: +12:22
+      }
+  
+      bb2: {
+          _5 = (*_2);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          _0 = opaque::<i32>(_5) -> bb3;   // scope 0 at $DIR/reference_prop.rs:+16:13: +16:38
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:357:28: 357:34
+                                           // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
+      }
+  
+      bb3: {
+          StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+19:13: +19:27
+          StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+20:13: +20:27
+          _6 = const true;                 // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          switchInt(_6) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/reference_prop.rs:+22:13: +22:47
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
new file mode 100644
index 00000000000..9dac0b333b8
--- /dev/null
+++ b/tests/mir-opt/reference_prop.maybe_dead.ReferencePropagation.diff
@@ -0,0 +1,50 @@
+- // MIR for `maybe_dead` before ReferencePropagation
++ // MIR for `maybe_dead` after ReferencePropagation
+  
+  fn maybe_dead(_1: bool) -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:24: +0:24
+      let mut _2: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _3: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _4: &i32;                    // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _5: &mut i32;                // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _6: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _7: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+  
+      bb0: {
+          StorageLive(_2);                 // scope 0 at $DIR/reference_prop.rs:+7:13: +7:27
+          StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+8:13: +8:27
+          _2 = const 5_i32;                // scope 0 at $DIR/reference_prop.rs:+9:13: +9:18
+          _3 = const 5_i32;                // scope 0 at $DIR/reference_prop.rs:+10:13: +10:18
+          _4 = &_2;                        // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          _5 = &mut _3;                    // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          (*_5) = const 7_i32;             // scope 0 at $DIR/reference_prop.rs:+14:13: +14:19
+          switchInt(_1) -> [1: bb1, otherwise: bb2]; // scope 0 at $DIR/reference_prop.rs:+15:13: +15:46
+      }
+  
+      bb1: {
+          StorageDead(_2);                 // scope 0 at $DIR/reference_prop.rs:+18:13: +18:27
+          StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+19:13: +19:27
+          goto -> bb2;                     // scope 0 at $DIR/reference_prop.rs:+20:13: +20:22
+      }
+  
+      bb2: {
+          _6 = (*_4);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          _0 = opaque::<i32>(_6) -> bb3;   // scope 0 at $DIR/reference_prop.rs:+25:13: +25:38
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:394:28: 394:34
+                                           // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
+      }
+  
+      bb3: {
+          _7 = (*_5);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          _0 = opaque::<i32>(_7) -> bb4;   // scope 0 at $DIR/reference_prop.rs:+31:13: +31:43
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:400:33: 400:39
+                                           // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
+      }
+  
+      bb4: {
+          return;                          // scope 0 at $DIR/reference_prop.rs:+34:13: +34:21
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
new file mode 100644
index 00000000000..994791072e1
--- /dev/null
+++ b/tests/mir-opt/reference_prop.multiple_storage.ReferencePropagation.diff
@@ -0,0 +1,27 @@
+- // MIR for `multiple_storage` before ReferencePropagation
++ // MIR for `multiple_storage` after ReferencePropagation
+  
+  fn multiple_storage() -> () {
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:23: +0:23
+      let mut _1: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _2: &i32;                    // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _3: i32;                     // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+6:13: +6:27
+          _1 = const 5_i32;                // scope 0 at $DIR/reference_prop.rs:+7:13: +7:18
+          _2 = &_1;                        // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          StorageDead(_1);                 // scope 0 at $DIR/reference_prop.rs:+9:13: +9:27
+          StorageLive(_1);                 // scope 0 at $DIR/reference_prop.rs:+10:13: +10:27
+          _3 = (*_2);                      // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+          _0 = opaque::<i32>(_3) -> bb1;   // scope 0 at $DIR/reference_prop.rs:+14:13: +14:43
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:331:33: 331:39
+                                           // + literal: Const { ty: fn(i32) {opaque::<i32>}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          return;                          // scope 0 at $DIR/reference_prop.rs:+18:13: +18:21
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff b/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff
new file mode 100644
index 00000000000..a7d505c6906
--- /dev/null
+++ b/tests/mir-opt/reference_prop.read_through_raw.ReferencePropagation.diff
@@ -0,0 +1,24 @@
+- // MIR for `read_through_raw` before ReferencePropagation
++ // MIR for `read_through_raw` after ReferencePropagation
+  
+  fn read_through_raw(_1: &mut usize) -> usize {
+      let mut _0: usize;                   // return place in scope 0 at $DIR/reference_prop.rs:+0:39: +0:44
+      let mut _2: &mut usize;              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _3: &mut usize;              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _4: *mut usize;              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+      let mut _5: *mut usize;              // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
+  
+      bb0: {
+          _2 = &mut (*_1);                 // scope 0 at $DIR/reference_prop.rs:+10:13: +10:25
+-         _3 = &mut (*_2);                 // scope 0 at $DIR/reference_prop.rs:+11:13: +11:26
+-         _4 = &raw mut (*_2);             // scope 0 at $DIR/reference_prop.rs:+12:13: +12:30
+-         _5 = &raw mut (*_3);             // scope 0 at $DIR/reference_prop.rs:+13:13: +13:30
+-         _0 = (*_4);                      // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
+-         _0 = (*_5);                      // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
++         _3 = &mut (*_1);                 // scope 0 at $DIR/reference_prop.rs:+11:13: +11:26
++         _0 = (*_2);                      // scope 0 at $DIR/reference_prop.rs:+15:13: +15:22
++         _0 = (*_3);                      // scope 0 at $DIR/reference_prop.rs:+16:13: +16:22
+          return;                          // scope 0 at $DIR/reference_prop.rs:+17:13: +17:21
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
new file mode 100644
index 00000000000..12aea890e63
--- /dev/null
+++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
@@ -0,0 +1,292 @@
+- // MIR for `reference_propagation` before ReferencePropagation
++ // MIR for `reference_propagation` after ReferencePropagation
+  
+  fn reference_propagation(_1: &T, _2: &T) -> () {
+      debug single => _1;                  // in scope 0 at $DIR/reference_prop.rs:+0:39: +0:45
+      debug multiple => _2;                // in scope 0 at $DIR/reference_prop.rs:+0:54: +0:66
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:75: +0:75
+      let _3: ();                          // in scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+      let _4: usize;                       // in scope 0 at $DIR/reference_prop.rs:+3:13: +3:14
+      let _7: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+      let _8: usize;                       // in scope 0 at $DIR/reference_prop.rs:+10:13: +10:14
+      let mut _11: &usize;                 // in scope 0 at $DIR/reference_prop.rs:+13:13: +13:16
+      let _12: &usize;                     // in scope 0 at $DIR/reference_prop.rs:+13:13: +13:16
+      let _14: ();                         // in scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+      let _15: usize;                      // in scope 0 at $DIR/reference_prop.rs:+20:13: +20:14
+      let _19: ();                         // in scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+      let _20: usize;                      // in scope 0 at $DIR/reference_prop.rs:+28:13: +28:14
+      let _24: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+      let _25: usize;                      // in scope 0 at $DIR/reference_prop.rs:+36:13: +36:14
+      let _28: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:9: +39:18
+      let mut _29: &usize;                 // in scope 0 at $DIR/reference_prop.rs:+39:16: +39:17
+      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+      let _31: usize;                      // in scope 0 at $DIR/reference_prop.rs:+44:13: +44:14
+      let _37: ();                         // in scope 0 at $DIR/reference_prop.rs:+52:9: +52:19
+      let mut _38: &usize;                 // in scope 0 at $DIR/reference_prop.rs:+52:16: +52:18
+      let _39: ();                         // in scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+      let _40: &T;                         // in scope 0 at $DIR/reference_prop.rs:+57:13: +57:14
+      let _42: &T;                         // in scope 0 at $DIR/reference_prop.rs:+63:13: +63:14
+      let mut _43: &T;                     // in scope 0 at $DIR/reference_prop.rs:+64:20: +64:28
+      let _44: &T;                         // in scope 0 at $DIR/reference_prop.rs:+64:20: +64:28
+      scope 1 {
+          debug a => _4;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
+          let _5: &usize;                  // in scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+          scope 2 {
+              debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+              let _6: usize;               // in scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
+              scope 3 {
+                  debug c => _6;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
+              }
+          }
+      }
+      scope 4 {
+          debug a => _8;                   // in scope 4 at $DIR/reference_prop.rs:+10:13: +10:14
+          let _9: usize;                   // in scope 4 at $DIR/reference_prop.rs:+11:13: +11:15
+          scope 5 {
+              debug a2 => _9;              // in scope 5 at $DIR/reference_prop.rs:+11:13: +11:15
+              let mut _10: &usize;         // in scope 5 at $DIR/reference_prop.rs:+12:13: +12:18
+              scope 6 {
+                  debug b => _10;          // in scope 6 at $DIR/reference_prop.rs:+12:13: +12:18
+                  let _13: usize;          // in scope 6 at $DIR/reference_prop.rs:+15:13: +15:14
+                  scope 7 {
+                      debug c => _13;      // in scope 7 at $DIR/reference_prop.rs:+15:13: +15:14
+                  }
+              }
+          }
+      }
+      scope 8 {
+          debug a => _15;                  // in scope 8 at $DIR/reference_prop.rs:+20:13: +20:14
+          let _16: &usize;                 // in scope 8 at $DIR/reference_prop.rs:+21:13: +21:14
+          scope 9 {
+              debug b => _16;              // in scope 9 at $DIR/reference_prop.rs:+21:13: +21:14
+              let _17: &&usize;            // in scope 9 at $DIR/reference_prop.rs:+22:13: +22:14
+              scope 10 {
+                  debug d => _17;          // in scope 10 at $DIR/reference_prop.rs:+22:13: +22:14
+                  let _18: usize;          // in scope 10 at $DIR/reference_prop.rs:+23:13: +23:14
+                  scope 11 {
+                      debug c => _18;      // in scope 11 at $DIR/reference_prop.rs:+23:13: +23:14
+                  }
+              }
+          }
+      }
+      scope 12 {
+          debug a => _20;                  // in scope 12 at $DIR/reference_prop.rs:+28:13: +28:14
+          let mut _21: &usize;             // in scope 12 at $DIR/reference_prop.rs:+29:13: +29:18
+          scope 13 {
+              debug b => _21;              // in scope 13 at $DIR/reference_prop.rs:+29:13: +29:18
+              let _22: &mut &usize;        // in scope 13 at $DIR/reference_prop.rs:+30:13: +30:14
+              scope 14 {
+                  debug d => _22;          // in scope 14 at $DIR/reference_prop.rs:+30:13: +30:14
+                  let _23: usize;          // in scope 14 at $DIR/reference_prop.rs:+31:13: +31:14
+                  scope 15 {
+                      debug c => _23;      // in scope 15 at $DIR/reference_prop.rs:+31:13: +31:14
+                  }
+              }
+          }
+      }
+      scope 16 {
+          debug a => _25;                  // in scope 16 at $DIR/reference_prop.rs:+36:13: +36:14
+          let _26: &usize;                 // in scope 16 at $DIR/reference_prop.rs:+37:13: +37:14
+          scope 17 {
+              debug b => _26;              // in scope 17 at $DIR/reference_prop.rs:+37:13: +37:14
+              let _27: usize;              // in scope 17 at $DIR/reference_prop.rs:+38:13: +38:14
+              scope 18 {
+                  debug c => _27;          // in scope 18 at $DIR/reference_prop.rs:+38:13: +38:14
+              }
+          }
+      }
+      scope 19 {
+          debug a => _31;                  // in scope 19 at $DIR/reference_prop.rs:+44:13: +44:14
+          let _32: &usize;                 // in scope 19 at $DIR/reference_prop.rs:+45:13: +45:15
+          scope 20 {
+              debug b1 => _32;             // in scope 20 at $DIR/reference_prop.rs:+45:13: +45:15
+              let _33: usize;              // in scope 20 at $DIR/reference_prop.rs:+46:13: +46:14
+              scope 21 {
+                  debug c => _33;          // in scope 21 at $DIR/reference_prop.rs:+46:13: +46:14
+                  let _34: &usize;         // in scope 21 at $DIR/reference_prop.rs:+47:13: +47:15
+                  scope 22 {
+                      debug b2 => _34;     // in scope 22 at $DIR/reference_prop.rs:+47:13: +47:15
+                      let _35: usize;      // in scope 22 at $DIR/reference_prop.rs:+48:13: +48:15
+                      scope 23 {
+                          debug c2 => _35; // in scope 23 at $DIR/reference_prop.rs:+48:13: +48:15
+                          let _36: &usize; // in scope 23 at $DIR/reference_prop.rs:+49:13: +49:15
+                          scope 24 {
+                              debug b3 => _36; // in scope 24 at $DIR/reference_prop.rs:+49:13: +49:15
+                          }
+                      }
+                  }
+              }
+          }
+      }
+      scope 25 {
+          debug a => _40;                  // in scope 25 at $DIR/reference_prop.rs:+57:13: +57:14
+          let _41: T;                      // in scope 25 at $DIR/reference_prop.rs:+58:13: +58:14
+          scope 26 {
+              debug b => _41;              // in scope 26 at $DIR/reference_prop.rs:+58:13: +58:14
+          }
+      }
+      scope 27 {
+          debug a => _42;                  // in scope 27 at $DIR/reference_prop.rs:+63:13: +63:14
+          let _45: T;                      // in scope 27 at $DIR/reference_prop.rs:+65:13: +65:14
+          scope 28 {
+              debug b => _45;              // in scope 28 at $DIR/reference_prop.rs:+65:13: +65:14
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+          StorageLive(_4);                 // scope 0 at $DIR/reference_prop.rs:+3:13: +3:14
+          _4 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+3:17: +3:24
+          StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+          _5 = &_4;                        // scope 1 at $DIR/reference_prop.rs:+4:17: +4:19
+          StorageLive(_6);                 // scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
+-         _6 = (*_5);                      // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
+-         _3 = const ();                   // scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
++         _6 = _4;                         // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
+          StorageDead(_6);                 // scope 2 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_4);                 // scope 0 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageLive(_7);                 // scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageLive(_8);                 // scope 0 at $DIR/reference_prop.rs:+10:13: +10:14
+          _8 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+10:17: +10:24
+          StorageLive(_9);                 // scope 4 at $DIR/reference_prop.rs:+11:13: +11:15
+          _9 = const 7_usize;              // scope 4 at $DIR/reference_prop.rs:+11:18: +11:25
+          StorageLive(_10);                // scope 5 at $DIR/reference_prop.rs:+12:13: +12:18
+          _10 = &_8;                       // scope 5 at $DIR/reference_prop.rs:+12:21: +12:23
+          StorageLive(_11);                // scope 6 at $DIR/reference_prop.rs:+13:13: +13:16
+-         StorageLive(_12);                // scope 6 at $DIR/reference_prop.rs:+13:13: +13:16
+-         _12 = &_9;                       // scope 6 at $DIR/reference_prop.rs:+13:13: +13:16
+-         _11 = &(*_12);                   // scope 6 at $DIR/reference_prop.rs:+13:13: +13:16
++         _11 = &_9;                       // scope 6 at $DIR/reference_prop.rs:+13:13: +13:16
+          _10 = move _11;                  // scope 6 at $DIR/reference_prop.rs:+13:9: +13:16
+          StorageDead(_11);                // scope 6 at $DIR/reference_prop.rs:+13:15: +13:16
+-         StorageDead(_12);                // scope 6 at $DIR/reference_prop.rs:+13:16: +13:17
+          StorageLive(_13);                // scope 6 at $DIR/reference_prop.rs:+15:13: +15:14
+          _13 = (*_10);                    // scope 6 at $DIR/reference_prop.rs:+15:17: +15:19
+-         _7 = const ();                   // scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageDead(_13);                // scope 6 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_10);                // scope 5 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_9);                 // scope 4 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_8);                 // scope 0 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageDead(_7);                 // scope 0 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageLive(_14);                // scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+          StorageLive(_15);                // scope 0 at $DIR/reference_prop.rs:+20:13: +20:14
+          _15 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+20:17: +20:24
+          StorageLive(_16);                // scope 8 at $DIR/reference_prop.rs:+21:13: +21:14
+          _16 = &_15;                      // scope 8 at $DIR/reference_prop.rs:+21:17: +21:19
+          StorageLive(_17);                // scope 9 at $DIR/reference_prop.rs:+22:13: +22:14
+          _17 = &_16;                      // scope 9 at $DIR/reference_prop.rs:+22:17: +22:19
+          StorageLive(_18);                // scope 10 at $DIR/reference_prop.rs:+23:13: +23:14
+-         _18 = (*_16);                    // scope 10 at $DIR/reference_prop.rs:+23:17: +23:19
+-         _14 = const ();                  // scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
++         _18 = _15;                       // scope 10 at $DIR/reference_prop.rs:+23:17: +23:19
+          StorageDead(_18);                // scope 10 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_17);                // scope 9 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_16);                // scope 8 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_15);                // scope 0 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageDead(_14);                // scope 0 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageLive(_19);                // scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageLive(_20);                // scope 0 at $DIR/reference_prop.rs:+28:13: +28:14
+          _20 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+28:17: +28:24
+          StorageLive(_21);                // scope 12 at $DIR/reference_prop.rs:+29:13: +29:18
+          _21 = &_20;                      // scope 12 at $DIR/reference_prop.rs:+29:21: +29:23
+          StorageLive(_22);                // scope 13 at $DIR/reference_prop.rs:+30:13: +30:14
+          _22 = &mut _21;                  // scope 13 at $DIR/reference_prop.rs:+30:17: +30:23
+          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+31:13: +31:14
+          _23 = (*_21);                    // scope 14 at $DIR/reference_prop.rs:+31:17: +31:19
+-         _19 = const ();                  // scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_22);                // scope 13 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_21);                // scope 12 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_20);                // scope 0 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageDead(_19);                // scope 0 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageLive(_24);                // scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageLive(_25);                // scope 0 at $DIR/reference_prop.rs:+36:13: +36:14
+          _25 = const 7_usize;             // scope 0 at $DIR/reference_prop.rs:+36:17: +36:24
+          StorageLive(_26);                // scope 16 at $DIR/reference_prop.rs:+37:13: +37:14
+          _26 = &_25;                      // scope 16 at $DIR/reference_prop.rs:+37:17: +37:19
+          StorageLive(_27);                // scope 17 at $DIR/reference_prop.rs:+38:13: +38:14
+-         _27 = (*_26);                    // scope 17 at $DIR/reference_prop.rs:+38:17: +38:19
++         _27 = _25;                       // scope 17 at $DIR/reference_prop.rs:+38:17: +38:19
+          StorageLive(_28);                // scope 18 at $DIR/reference_prop.rs:+39:9: +39:18
+          StorageLive(_29);                // scope 18 at $DIR/reference_prop.rs:+39:16: +39:17
+          _29 = _26;                       // scope 18 at $DIR/reference_prop.rs:+39:16: +39:17
+          _28 = opaque::<&usize>(move _29) -> bb1; // scope 18 at $DIR/reference_prop.rs:+39:9: +39:18
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:48:9: 48:15
+                                           // + literal: Const { ty: fn(&usize) {opaque::<&usize>}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_29);                // scope 18 at $DIR/reference_prop.rs:+39:17: +39:18
+          StorageDead(_28);                // scope 18 at $DIR/reference_prop.rs:+39:18: +39:19
+-         _24 = const ();                  // scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageDead(_27);                // scope 17 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_26);                // scope 16 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_25);                // scope 0 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageDead(_24);                // scope 0 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageLive(_30);                // scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageLive(_31);                // scope 0 at $DIR/reference_prop.rs:+44:13: +44:14
+          _31 = const 7_usize;             // scope 0 at $DIR/reference_prop.rs:+44:17: +44:24
+          StorageLive(_32);                // scope 19 at $DIR/reference_prop.rs:+45:13: +45:15
+          _32 = &_31;                      // scope 19 at $DIR/reference_prop.rs:+45:18: +45:20
+          StorageLive(_33);                // scope 20 at $DIR/reference_prop.rs:+46:13: +46:14
+-         _33 = (*_32);                    // scope 20 at $DIR/reference_prop.rs:+46:17: +46:20
++         _33 = _31;                       // scope 20 at $DIR/reference_prop.rs:+46:17: +46:20
+          StorageLive(_34);                // scope 21 at $DIR/reference_prop.rs:+47:13: +47:15
+          _34 = _32;                       // scope 21 at $DIR/reference_prop.rs:+47:18: +47:20
+          StorageLive(_35);                // scope 22 at $DIR/reference_prop.rs:+48:13: +48:15
+-         _35 = (*_34);                    // scope 22 at $DIR/reference_prop.rs:+48:18: +48:21
++         _35 = _31;                       // scope 22 at $DIR/reference_prop.rs:+48:18: +48:21
+          StorageLive(_36);                // scope 23 at $DIR/reference_prop.rs:+49:13: +49:15
+          _36 = _34;                       // scope 23 at $DIR/reference_prop.rs:+49:18: +49:20
+          StorageLive(_37);                // scope 24 at $DIR/reference_prop.rs:+52:9: +52:19
+          StorageLive(_38);                // scope 24 at $DIR/reference_prop.rs:+52:16: +52:18
+          _38 = _36;                       // scope 24 at $DIR/reference_prop.rs:+52:16: +52:18
+          _37 = opaque::<&usize>(move _38) -> bb2; // scope 24 at $DIR/reference_prop.rs:+52:9: +52:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:61:9: 61:15
+                                           // + literal: Const { ty: fn(&usize) {opaque::<&usize>}, val: Value(<ZST>) }
+      }
+  
+      bb2: {
+          StorageDead(_38);                // scope 24 at $DIR/reference_prop.rs:+52:18: +52:19
+          StorageDead(_37);                // scope 24 at $DIR/reference_prop.rs:+52:19: +52:20
+-         _30 = const ();                  // scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageDead(_36);                // scope 23 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_35);                // scope 22 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_34);                // scope 21 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_33);                // scope 20 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_32);                // scope 19 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_31);                // scope 0 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageDead(_30);                // scope 0 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageLive(_39);                // scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+          StorageLive(_40);                // scope 0 at $DIR/reference_prop.rs:+57:13: +57:14
+          _40 = &(*_1);                    // scope 0 at $DIR/reference_prop.rs:+57:17: +57:25
+          StorageLive(_41);                // scope 25 at $DIR/reference_prop.rs:+58:13: +58:14
+-         _41 = (*_40);                    // scope 25 at $DIR/reference_prop.rs:+58:17: +58:19
+-         _39 = const ();                  // scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
++         _41 = (*_1);                     // scope 25 at $DIR/reference_prop.rs:+58:17: +58:19
+          StorageDead(_41);                // scope 25 at $DIR/reference_prop.rs:+59:5: +59:6
+          StorageDead(_40);                // scope 0 at $DIR/reference_prop.rs:+59:5: +59:6
+-         StorageDead(_39);                // scope 0 at $DIR/reference_prop.rs:+59:5: +59:6
+          StorageLive(_42);                // scope 0 at $DIR/reference_prop.rs:+63:13: +63:14
+          _42 = &(*_2);                    // scope 0 at $DIR/reference_prop.rs:+63:17: +63:27
+          StorageLive(_43);                // scope 27 at $DIR/reference_prop.rs:+64:20: +64:28
+-         StorageLive(_44);                // scope 27 at $DIR/reference_prop.rs:+64:20: +64:28
+-         _44 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+64:20: +64:28
+-         _43 = &(*_44);                   // scope 27 at $DIR/reference_prop.rs:+64:20: +64:28
++         _43 = &(*_1);                    // scope 27 at $DIR/reference_prop.rs:+64:20: +64:28
+          _2 = move _43;                   // scope 27 at $DIR/reference_prop.rs:+64:9: +64:28
+          StorageDead(_43);                // scope 27 at $DIR/reference_prop.rs:+64:27: +64:28
+-         StorageDead(_44);                // scope 27 at $DIR/reference_prop.rs:+64:28: +64:29
+          StorageLive(_45);                // scope 27 at $DIR/reference_prop.rs:+65:13: +65:14
+          _45 = (*_42);                    // scope 27 at $DIR/reference_prop.rs:+65:17: +65:19
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+62:5: +66:6
+          StorageDead(_45);                // scope 27 at $DIR/reference_prop.rs:+66:5: +66:6
+          StorageDead(_42);                // scope 0 at $DIR/reference_prop.rs:+66:5: +66:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+67:2: +67:2
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
new file mode 100644
index 00000000000..2e6097af2c9
--- /dev/null
+++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
@@ -0,0 +1,334 @@
+- // MIR for `reference_propagation_const_ptr` before ReferencePropagation
++ // MIR for `reference_propagation_const_ptr` after ReferencePropagation
+  
+  fn reference_propagation_const_ptr(_1: *const T, _2: *const T) -> () {
+      debug single => _1;                  // in scope 0 at $DIR/reference_prop.rs:+0:45: +0:51
+      debug multiple => _2;                // in scope 0 at $DIR/reference_prop.rs:+0:63: +0:75
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:87: +0:87
+      let _3: ();                          // in scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+      let _7: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+      let mut _11: *const usize;           // in scope 0 at $DIR/reference_prop.rs:+13:13: +13:26
+      let _13: ();                         // in scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+      let _18: ();                         // in scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+      let _27: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:9: +39:18
+      let mut _28: *const usize;           // in scope 0 at $DIR/reference_prop.rs:+39:16: +39:17
+      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+      let _36: ();                         // in scope 0 at $DIR/reference_prop.rs:+52:9: +52:19
+      let mut _37: *const usize;           // in scope 0 at $DIR/reference_prop.rs:+52:16: +52:18
+      let _38: ();                         // in scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+      let _41: ();                         // in scope 0 at $DIR/reference_prop.rs:+62:5: +66:6
+      let mut _43: *const T;               // in scope 0 at $DIR/reference_prop.rs:+64:20: +64:38
+      scope 1 {
+          let _4: usize;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
+          scope 2 {
+              debug a => _4;               // in scope 2 at $DIR/reference_prop.rs:+3:13: +3:14
+              let _5: *const usize;        // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+              scope 3 {
+                  debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
+                  let _6: usize;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
+                  scope 4 {
+                      debug c => _6;       // in scope 4 at $DIR/reference_prop.rs:+5:13: +5:14
+                  }
+              }
+          }
+      }
+      scope 5 {
+          let _8: usize;                   // in scope 5 at $DIR/reference_prop.rs:+10:13: +10:14
+          scope 6 {
+              debug a => _8;               // in scope 6 at $DIR/reference_prop.rs:+10:13: +10:14
+              let _9: usize;               // in scope 6 at $DIR/reference_prop.rs:+11:13: +11:15
+              scope 7 {
+                  debug a2 => _9;          // in scope 7 at $DIR/reference_prop.rs:+11:13: +11:15
+                  let mut _10: *const usize; // in scope 7 at $DIR/reference_prop.rs:+12:13: +12:18
+                  scope 8 {
+                      debug b => _10;      // in scope 8 at $DIR/reference_prop.rs:+12:13: +12:18
+                      let _12: usize;      // in scope 8 at $DIR/reference_prop.rs:+15:13: +15:14
+                      scope 9 {
+                          debug c => _12;  // in scope 9 at $DIR/reference_prop.rs:+15:13: +15:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 10 {
+          let _14: usize;                  // in scope 10 at $DIR/reference_prop.rs:+20:13: +20:14
+          scope 11 {
+              debug a => _14;              // in scope 11 at $DIR/reference_prop.rs:+20:13: +20:14
+              let _15: *const usize;       // in scope 11 at $DIR/reference_prop.rs:+21:13: +21:14
+              scope 12 {
+                  debug b => _15;          // in scope 12 at $DIR/reference_prop.rs:+21:13: +21:14
+                  let _16: &*const usize;  // in scope 12 at $DIR/reference_prop.rs:+22:13: +22:14
+                  scope 13 {
+                      debug d => _16;      // in scope 13 at $DIR/reference_prop.rs:+22:13: +22:14
+                      let _17: usize;      // in scope 13 at $DIR/reference_prop.rs:+23:13: +23:14
+                      scope 14 {
+                          debug c => _17;  // in scope 14 at $DIR/reference_prop.rs:+23:13: +23:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 15 {
+          let _19: usize;                  // in scope 15 at $DIR/reference_prop.rs:+28:13: +28:14
+          scope 16 {
+              debug a => _19;              // in scope 16 at $DIR/reference_prop.rs:+28:13: +28:14
+              let mut _20: *const usize;   // in scope 16 at $DIR/reference_prop.rs:+29:13: +29:18
+              scope 17 {
+                  debug b => _20;          // in scope 17 at $DIR/reference_prop.rs:+29:13: +29:18
+                  let _21: &mut *const usize; // in scope 17 at $DIR/reference_prop.rs:+30:13: +30:14
+                  scope 18 {
+                      debug d => _21;      // in scope 18 at $DIR/reference_prop.rs:+30:13: +30:14
+                      let _22: usize;      // in scope 18 at $DIR/reference_prop.rs:+31:13: +31:14
+                      scope 19 {
+                          debug c => _22;  // in scope 19 at $DIR/reference_prop.rs:+31:13: +31:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 20 {
+          let _24: usize;                  // in scope 20 at $DIR/reference_prop.rs:+36:13: +36:14
+          scope 21 {
+              debug a => _24;              // in scope 21 at $DIR/reference_prop.rs:+36:13: +36:14
+              let _25: *const usize;       // in scope 21 at $DIR/reference_prop.rs:+37:13: +37:14
+              scope 22 {
+                  debug b => _25;          // in scope 22 at $DIR/reference_prop.rs:+37:13: +37:14
+                  let _26: usize;          // in scope 22 at $DIR/reference_prop.rs:+38:13: +38:14
+                  scope 23 {
+                      debug c => _26;      // in scope 23 at $DIR/reference_prop.rs:+38:13: +38:14
+                  }
+              }
+          }
+      }
+      scope 24 {
+          let _30: usize;                  // in scope 24 at $DIR/reference_prop.rs:+44:13: +44:14
+          scope 25 {
+              debug a => _30;              // in scope 25 at $DIR/reference_prop.rs:+44:13: +44:14
+              let _31: *const usize;       // in scope 25 at $DIR/reference_prop.rs:+45:13: +45:15
+              scope 26 {
+                  debug b1 => _31;         // in scope 26 at $DIR/reference_prop.rs:+45:13: +45:15
+                  let _32: usize;          // in scope 26 at $DIR/reference_prop.rs:+46:13: +46:14
+                  scope 27 {
+                      debug c => _32;      // in scope 27 at $DIR/reference_prop.rs:+46:13: +46:14
+                      let _33: *const usize; // in scope 27 at $DIR/reference_prop.rs:+47:13: +47:15
+                      scope 28 {
+                          debug b2 => _33; // in scope 28 at $DIR/reference_prop.rs:+47:13: +47:15
+                          let _34: usize;  // in scope 28 at $DIR/reference_prop.rs:+48:13: +48:15
+                          scope 29 {
+                              debug c2 => _34; // in scope 29 at $DIR/reference_prop.rs:+48:13: +48:15
+                              let _35: *const usize; // in scope 29 at $DIR/reference_prop.rs:+49:13: +49:15
+                              scope 30 {
+                                  debug b3 => _35; // in scope 30 at $DIR/reference_prop.rs:+49:13: +49:15
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+      scope 31 {
+          let _39: *const T;               // in scope 31 at $DIR/reference_prop.rs:+57:13: +57:14
+          scope 32 {
+              debug a => _39;              // in scope 32 at $DIR/reference_prop.rs:+57:13: +57:14
+              let _40: T;                  // in scope 32 at $DIR/reference_prop.rs:+58:13: +58:14
+              scope 33 {
+                  debug b => _40;          // in scope 33 at $DIR/reference_prop.rs:+58:13: +58:14
+              }
+          }
+      }
+      scope 34 {
+          let _42: *const T;               // in scope 34 at $DIR/reference_prop.rs:+63:13: +63:14
+          scope 35 {
+              debug a => _42;              // in scope 35 at $DIR/reference_prop.rs:+63:13: +63:14
+              let _44: T;                  // in scope 35 at $DIR/reference_prop.rs:+65:13: +65:14
+              scope 36 {
+                  debug b => _44;          // in scope 36 at $DIR/reference_prop.rs:+65:13: +65:14
+              }
+          }
+      }
+      scope 37 {
+          let _45: usize;                  // in scope 37 at $DIR/reference_prop.rs:+70:13: +70:14
+          scope 38 {
+              debug a => _45;              // in scope 38 at $DIR/reference_prop.rs:+70:13: +70:14
+              let _46: *const usize;       // in scope 38 at $DIR/reference_prop.rs:+71:13: +71:14
+              scope 39 {
+                  debug b => _46;          // in scope 39 at $DIR/reference_prop.rs:+71:13: +71:14
+                  let _47: *const usize;   // in scope 39 at $DIR/reference_prop.rs:+72:13: +72:14
+                  scope 40 {
+                      debug c => _47;      // in scope 40 at $DIR/reference_prop.rs:+72:13: +72:14
+                      let _48: usize;      // in scope 40 at $DIR/reference_prop.rs:+73:13: +73:14
+                      scope 41 {
+                          debug e => _48;  // in scope 41 at $DIR/reference_prop.rs:+73:13: +73:14
+                      }
+                  }
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+          StorageLive(_4);                 // scope 1 at $DIR/reference_prop.rs:+3:13: +3:14
+          _4 = const 5_usize;              // scope 1 at $DIR/reference_prop.rs:+3:17: +3:24
+          StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+          _5 = &raw const _4;              // scope 2 at $DIR/reference_prop.rs:+4:17: +4:29
+          StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
+-         _6 = (*_5);                      // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
+-         _3 = const ();                   // scope 1 at $DIR/reference_prop.rs:+2:5: +6:6
++         _6 = _4;                         // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
+          StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_4);                 // scope 1 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageLive(_7);                 // scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageLive(_8);                 // scope 5 at $DIR/reference_prop.rs:+10:13: +10:14
+          _8 = const 5_usize;              // scope 5 at $DIR/reference_prop.rs:+10:17: +10:24
+          StorageLive(_9);                 // scope 6 at $DIR/reference_prop.rs:+11:13: +11:15
+          _9 = const 7_usize;              // scope 6 at $DIR/reference_prop.rs:+11:18: +11:25
+          StorageLive(_10);                // scope 7 at $DIR/reference_prop.rs:+12:13: +12:18
+          _10 = &raw const _8;             // scope 7 at $DIR/reference_prop.rs:+12:21: +12:33
+          StorageLive(_11);                // scope 8 at $DIR/reference_prop.rs:+13:13: +13:26
+          _11 = &raw const _9;             // scope 8 at $DIR/reference_prop.rs:+13:13: +13:26
+          _10 = move _11;                  // scope 8 at $DIR/reference_prop.rs:+13:9: +13:26
+          StorageDead(_11);                // scope 8 at $DIR/reference_prop.rs:+13:25: +13:26
+          StorageLive(_12);                // scope 8 at $DIR/reference_prop.rs:+15:13: +15:14
+          _12 = (*_10);                    // scope 8 at $DIR/reference_prop.rs:+15:17: +15:19
+-         _7 = const ();                   // scope 5 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageDead(_12);                // scope 8 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_10);                // scope 7 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_9);                 // scope 6 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_8);                 // scope 5 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageDead(_7);                 // scope 0 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageLive(_13);                // scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+          StorageLive(_14);                // scope 10 at $DIR/reference_prop.rs:+20:13: +20:14
+          _14 = const 5_usize;             // scope 10 at $DIR/reference_prop.rs:+20:17: +20:24
+          StorageLive(_15);                // scope 11 at $DIR/reference_prop.rs:+21:13: +21:14
+          _15 = &raw const _14;            // scope 11 at $DIR/reference_prop.rs:+21:17: +21:29
+          StorageLive(_16);                // scope 12 at $DIR/reference_prop.rs:+22:13: +22:14
+          _16 = &_15;                      // scope 12 at $DIR/reference_prop.rs:+22:17: +22:19
+          StorageLive(_17);                // scope 13 at $DIR/reference_prop.rs:+23:13: +23:14
+-         _17 = (*_15);                    // scope 13 at $DIR/reference_prop.rs:+23:17: +23:19
+-         _13 = const ();                  // scope 10 at $DIR/reference_prop.rs:+19:5: +24:6
++         _17 = _14;                       // scope 13 at $DIR/reference_prop.rs:+23:17: +23:19
+          StorageDead(_17);                // scope 13 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_16);                // scope 12 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_15);                // scope 11 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_14);                // scope 10 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageDead(_13);                // scope 0 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageLive(_18);                // scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageLive(_19);                // scope 15 at $DIR/reference_prop.rs:+28:13: +28:14
+          _19 = const 5_usize;             // scope 15 at $DIR/reference_prop.rs:+28:17: +28:24
+          StorageLive(_20);                // scope 16 at $DIR/reference_prop.rs:+29:13: +29:18
+          _20 = &raw const _19;            // scope 16 at $DIR/reference_prop.rs:+29:21: +29:33
+          StorageLive(_21);                // scope 17 at $DIR/reference_prop.rs:+30:13: +30:14
+          _21 = &mut _20;                  // scope 17 at $DIR/reference_prop.rs:+30:17: +30:23
+          StorageLive(_22);                // scope 18 at $DIR/reference_prop.rs:+31:13: +31:14
+          _22 = (*_20);                    // scope 18 at $DIR/reference_prop.rs:+31:17: +31:19
+-         _18 = const ();                  // scope 15 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageDead(_22);                // scope 18 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_21);                // scope 17 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_20);                // scope 16 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_19);                // scope 15 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageDead(_18);                // scope 0 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageLive(_23);                // scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageLive(_24);                // scope 20 at $DIR/reference_prop.rs:+36:13: +36:14
+          _24 = const 7_usize;             // scope 20 at $DIR/reference_prop.rs:+36:17: +36:24
+          StorageLive(_25);                // scope 21 at $DIR/reference_prop.rs:+37:13: +37:14
+          _25 = &raw const _24;            // scope 21 at $DIR/reference_prop.rs:+37:17: +37:29
+          StorageLive(_26);                // scope 22 at $DIR/reference_prop.rs:+38:13: +38:14
+-         _26 = (*_25);                    // scope 22 at $DIR/reference_prop.rs:+38:17: +38:19
++         _26 = _24;                       // scope 22 at $DIR/reference_prop.rs:+38:17: +38:19
+          StorageLive(_27);                // scope 23 at $DIR/reference_prop.rs:+39:9: +39:18
+          StorageLive(_28);                // scope 23 at $DIR/reference_prop.rs:+39:16: +39:17
+          _28 = _25;                       // scope 23 at $DIR/reference_prop.rs:+39:16: +39:17
+          _27 = opaque::<*const usize>(move _28) -> bb1; // scope 23 at $DIR/reference_prop.rs:+39:9: +39:18
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:186:9: 186:15
+                                           // + literal: Const { ty: fn(*const usize) {opaque::<*const usize>}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_28);                // scope 23 at $DIR/reference_prop.rs:+39:17: +39:18
+          StorageDead(_27);                // scope 23 at $DIR/reference_prop.rs:+39:18: +39:19
+-         _23 = const ();                  // scope 20 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageDead(_26);                // scope 22 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_25);                // scope 21 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_24);                // scope 20 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageDead(_23);                // scope 0 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageLive(_29);                // scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageLive(_30);                // scope 24 at $DIR/reference_prop.rs:+44:13: +44:14
+          _30 = const 7_usize;             // scope 24 at $DIR/reference_prop.rs:+44:17: +44:24
+          StorageLive(_31);                // scope 25 at $DIR/reference_prop.rs:+45:13: +45:15
+          _31 = &raw const _30;            // scope 25 at $DIR/reference_prop.rs:+45:18: +45:30
+          StorageLive(_32);                // scope 26 at $DIR/reference_prop.rs:+46:13: +46:14
+-         _32 = (*_31);                    // scope 26 at $DIR/reference_prop.rs:+46:17: +46:20
++         _32 = _30;                       // scope 26 at $DIR/reference_prop.rs:+46:17: +46:20
+          StorageLive(_33);                // scope 27 at $DIR/reference_prop.rs:+47:13: +47:15
+          _33 = _31;                       // scope 27 at $DIR/reference_prop.rs:+47:18: +47:20
+          StorageLive(_34);                // scope 28 at $DIR/reference_prop.rs:+48:13: +48:15
+-         _34 = (*_33);                    // scope 28 at $DIR/reference_prop.rs:+48:18: +48:21
++         _34 = _30;                       // scope 28 at $DIR/reference_prop.rs:+48:18: +48:21
+          StorageLive(_35);                // scope 29 at $DIR/reference_prop.rs:+49:13: +49:15
+          _35 = _33;                       // scope 29 at $DIR/reference_prop.rs:+49:18: +49:20
+          StorageLive(_36);                // scope 30 at $DIR/reference_prop.rs:+52:9: +52:19
+          StorageLive(_37);                // scope 30 at $DIR/reference_prop.rs:+52:16: +52:18
+          _37 = _35;                       // scope 30 at $DIR/reference_prop.rs:+52:16: +52:18
+          _36 = opaque::<*const usize>(move _37) -> bb2; // scope 30 at $DIR/reference_prop.rs:+52:9: +52:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:199:9: 199:15
+                                           // + literal: Const { ty: fn(*const usize) {opaque::<*const usize>}, val: Value(<ZST>) }
+      }
+  
+      bb2: {
+          StorageDead(_37);                // scope 30 at $DIR/reference_prop.rs:+52:18: +52:19
+          StorageDead(_36);                // scope 30 at $DIR/reference_prop.rs:+52:19: +52:20
+-         _29 = const ();                  // scope 24 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageDead(_35);                // scope 29 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_34);                // scope 28 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_33);                // scope 27 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_32);                // scope 26 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_31);                // scope 25 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_30);                // scope 24 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageDead(_29);                // scope 0 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageLive(_38);                // scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+          StorageLive(_39);                // scope 31 at $DIR/reference_prop.rs:+57:13: +57:14
+          _39 = &raw const (*_1);          // scope 31 at $DIR/reference_prop.rs:+57:17: +57:35
+          StorageLive(_40);                // scope 32 at $DIR/reference_prop.rs:+58:13: +58:14
+-         _40 = (*_39);                    // scope 32 at $DIR/reference_prop.rs:+58:17: +58:19
+-         _38 = const ();                  // scope 31 at $DIR/reference_prop.rs:+56:5: +59:6
++         _40 = (*_1);                     // scope 32 at $DIR/reference_prop.rs:+58:17: +58:19
+          StorageDead(_40);                // scope 32 at $DIR/reference_prop.rs:+59:5: +59:6
+          StorageDead(_39);                // scope 31 at $DIR/reference_prop.rs:+59:5: +59:6
+-         StorageDead(_38);                // scope 0 at $DIR/reference_prop.rs:+59:5: +59:6
+-         StorageLive(_41);                // scope 0 at $DIR/reference_prop.rs:+62:5: +66:6
+          StorageLive(_42);                // scope 34 at $DIR/reference_prop.rs:+63:13: +63:14
+          _42 = &raw const (*_2);          // scope 34 at $DIR/reference_prop.rs:+63:17: +63:37
+          StorageLive(_43);                // scope 35 at $DIR/reference_prop.rs:+64:20: +64:38
+          _43 = &raw const (*_1);          // scope 35 at $DIR/reference_prop.rs:+64:20: +64:38
+          _2 = move _43;                   // scope 35 at $DIR/reference_prop.rs:+64:9: +64:38
+          StorageDead(_43);                // scope 35 at $DIR/reference_prop.rs:+64:37: +64:38
+          StorageLive(_44);                // scope 35 at $DIR/reference_prop.rs:+65:13: +65:14
+          _44 = (*_42);                    // scope 35 at $DIR/reference_prop.rs:+65:17: +65:19
+-         _41 = const ();                  // scope 34 at $DIR/reference_prop.rs:+62:5: +66:6
+          StorageDead(_44);                // scope 35 at $DIR/reference_prop.rs:+66:5: +66:6
+          StorageDead(_42);                // scope 34 at $DIR/reference_prop.rs:+66:5: +66:6
+-         StorageDead(_41);                // scope 0 at $DIR/reference_prop.rs:+66:5: +66:6
+          StorageLive(_45);                // scope 37 at $DIR/reference_prop.rs:+70:13: +70:14
+          _45 = const 13_usize;            // scope 37 at $DIR/reference_prop.rs:+70:17: +70:25
+          StorageLive(_46);                // scope 38 at $DIR/reference_prop.rs:+71:13: +71:14
+          _46 = &raw const _45;            // scope 38 at $DIR/reference_prop.rs:+71:17: +71:29
+          StorageLive(_47);                // scope 39 at $DIR/reference_prop.rs:+72:13: +72:14
+-         _47 = &raw const (*_46);         // scope 39 at $DIR/reference_prop.rs:+72:17: +72:30
++         _47 = &raw const _45;            // scope 39 at $DIR/reference_prop.rs:+72:17: +72:30
+          StorageLive(_48);                // scope 40 at $DIR/reference_prop.rs:+73:13: +73:14
+-         _48 = (*_47);                    // scope 40 at $DIR/reference_prop.rs:+73:17: +73:19
++         _48 = _45;                       // scope 40 at $DIR/reference_prop.rs:+73:17: +73:19
+          _0 = const ();                   // scope 37 at $DIR/reference_prop.rs:+69:5: +74:6
+          StorageDead(_48);                // scope 40 at $DIR/reference_prop.rs:+74:5: +74:6
+          StorageDead(_47);                // scope 39 at $DIR/reference_prop.rs:+74:5: +74:6
+          StorageDead(_46);                // scope 38 at $DIR/reference_prop.rs:+74:5: +74:6
+          StorageDead(_45);                // scope 37 at $DIR/reference_prop.rs:+74:5: +74:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+75:2: +75:2
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
new file mode 100644
index 00000000000..f7bbd2a03f9
--- /dev/null
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
@@ -0,0 +1,288 @@
+- // MIR for `reference_propagation_mut` before ReferencePropagation
++ // MIR for `reference_propagation_mut` after ReferencePropagation
+  
+  fn reference_propagation_mut(_1: &mut T, _2: &mut T) -> () {
+      debug single => _1;                  // in scope 0 at $DIR/reference_prop.rs:+0:43: +0:49
+      debug multiple => _2;                // in scope 0 at $DIR/reference_prop.rs:+0:62: +0:74
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:87: +0:87
+      let _3: ();                          // in scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+      let mut _4: usize;                   // in scope 0 at $DIR/reference_prop.rs:+3:13: +3:18
+      let _7: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+      let mut _8: usize;                   // in scope 0 at $DIR/reference_prop.rs:+10:13: +10:18
+      let mut _11: &mut usize;             // in scope 0 at $DIR/reference_prop.rs:+13:13: +13:20
+      let mut _12: &mut usize;             // in scope 0 at $DIR/reference_prop.rs:+13:13: +13:20
+      let _14: ();                         // in scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+      let mut _15: usize;                  // in scope 0 at $DIR/reference_prop.rs:+20:13: +20:18
+      let _19: ();                         // in scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+      let mut _20: usize;                  // in scope 0 at $DIR/reference_prop.rs:+28:13: +28:18
+      let _24: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+      let mut _25: usize;                  // in scope 0 at $DIR/reference_prop.rs:+36:13: +36:18
+      let _28: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:9: +39:18
+      let mut _29: &mut usize;             // in scope 0 at $DIR/reference_prop.rs:+39:16: +39:17
+      let _30: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+      let mut _31: usize;                  // in scope 0 at $DIR/reference_prop.rs:+44:13: +44:18
+      let _37: ();                         // in scope 0 at $DIR/reference_prop.rs:+52:9: +52:19
+      let mut _38: &mut usize;             // in scope 0 at $DIR/reference_prop.rs:+52:16: +52:18
+      let _39: ();                         // in scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+      let _40: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+57:13: +57:14
+      let _42: &mut T;                     // in scope 0 at $DIR/reference_prop.rs:+63:13: +63:14
+      let mut _43: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+64:20: +64:32
+      let mut _44: &mut T;                 // in scope 0 at $DIR/reference_prop.rs:+64:20: +64:32
+      scope 1 {
+          debug a => _4;                   // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
+          let _5: &mut usize;              // in scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+          scope 2 {
+              debug b => _5;               // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+              let _6: usize;               // in scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
+              scope 3 {
+                  debug c => _6;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
+              }
+          }
+      }
+      scope 4 {
+          debug a => _8;                   // in scope 4 at $DIR/reference_prop.rs:+10:13: +10:18
+          let mut _9: usize;               // in scope 4 at $DIR/reference_prop.rs:+11:13: +11:19
+          scope 5 {
+              debug a2 => _9;              // in scope 5 at $DIR/reference_prop.rs:+11:13: +11:19
+              let mut _10: &mut usize;     // in scope 5 at $DIR/reference_prop.rs:+12:13: +12:18
+              scope 6 {
+                  debug b => _10;          // in scope 6 at $DIR/reference_prop.rs:+12:13: +12:18
+                  let _13: usize;          // in scope 6 at $DIR/reference_prop.rs:+15:13: +15:14
+                  scope 7 {
+                      debug c => _13;      // in scope 7 at $DIR/reference_prop.rs:+15:13: +15:14
+                  }
+              }
+          }
+      }
+      scope 8 {
+          debug a => _15;                  // in scope 8 at $DIR/reference_prop.rs:+20:13: +20:18
+          let _16: &mut usize;             // in scope 8 at $DIR/reference_prop.rs:+21:13: +21:14
+          scope 9 {
+              debug b => _16;              // in scope 9 at $DIR/reference_prop.rs:+21:13: +21:14
+              let _17: &&mut usize;        // in scope 9 at $DIR/reference_prop.rs:+22:13: +22:14
+              scope 10 {
+                  debug d => _17;          // in scope 10 at $DIR/reference_prop.rs:+22:13: +22:14
+                  let _18: usize;          // in scope 10 at $DIR/reference_prop.rs:+23:13: +23:14
+                  scope 11 {
+                      debug c => _18;      // in scope 11 at $DIR/reference_prop.rs:+23:13: +23:14
+                  }
+              }
+          }
+      }
+      scope 12 {
+          debug a => _20;                  // in scope 12 at $DIR/reference_prop.rs:+28:13: +28:18
+          let mut _21: &mut usize;         // in scope 12 at $DIR/reference_prop.rs:+29:13: +29:18
+          scope 13 {
+              debug b => _21;              // in scope 13 at $DIR/reference_prop.rs:+29:13: +29:18
+              let _22: &mut &mut usize;    // in scope 13 at $DIR/reference_prop.rs:+30:13: +30:14
+              scope 14 {
+                  debug d => _22;          // in scope 14 at $DIR/reference_prop.rs:+30:13: +30:14
+                  let _23: usize;          // in scope 14 at $DIR/reference_prop.rs:+31:13: +31:14
+                  scope 15 {
+                      debug c => _23;      // in scope 15 at $DIR/reference_prop.rs:+31:13: +31:14
+                  }
+              }
+          }
+      }
+      scope 16 {
+          debug a => _25;                  // in scope 16 at $DIR/reference_prop.rs:+36:13: +36:18
+          let _26: &mut usize;             // in scope 16 at $DIR/reference_prop.rs:+37:13: +37:14
+          scope 17 {
+              debug b => _26;              // in scope 17 at $DIR/reference_prop.rs:+37:13: +37:14
+              let _27: usize;              // in scope 17 at $DIR/reference_prop.rs:+38:13: +38:14
+              scope 18 {
+                  debug c => _27;          // in scope 18 at $DIR/reference_prop.rs:+38:13: +38:14
+              }
+          }
+      }
+      scope 19 {
+          debug a => _31;                  // in scope 19 at $DIR/reference_prop.rs:+44:13: +44:18
+          let _32: &mut usize;             // in scope 19 at $DIR/reference_prop.rs:+45:13: +45:15
+          scope 20 {
+              debug b1 => _32;             // in scope 20 at $DIR/reference_prop.rs:+45:13: +45:15
+              let _33: usize;              // in scope 20 at $DIR/reference_prop.rs:+46:13: +46:14
+              scope 21 {
+                  debug c => _33;          // in scope 21 at $DIR/reference_prop.rs:+46:13: +46:14
+                  let _34: &mut usize;     // in scope 21 at $DIR/reference_prop.rs:+47:13: +47:15
+                  scope 22 {
+                      debug b2 => _34;     // in scope 22 at $DIR/reference_prop.rs:+47:13: +47:15
+                      let _35: usize;      // in scope 22 at $DIR/reference_prop.rs:+48:13: +48:15
+                      scope 23 {
+                          debug c2 => _35; // in scope 23 at $DIR/reference_prop.rs:+48:13: +48:15
+                          let _36: &mut usize; // in scope 23 at $DIR/reference_prop.rs:+49:13: +49:15
+                          scope 24 {
+                              debug b3 => _36; // in scope 24 at $DIR/reference_prop.rs:+49:13: +49:15
+                          }
+                      }
+                  }
+              }
+          }
+      }
+      scope 25 {
+          debug a => _40;                  // in scope 25 at $DIR/reference_prop.rs:+57:13: +57:14
+          let _41: T;                      // in scope 25 at $DIR/reference_prop.rs:+58:13: +58:14
+          scope 26 {
+              debug b => _41;              // in scope 26 at $DIR/reference_prop.rs:+58:13: +58:14
+          }
+      }
+      scope 27 {
+          debug a => _42;                  // in scope 27 at $DIR/reference_prop.rs:+63:13: +63:14
+          let _45: T;                      // in scope 27 at $DIR/reference_prop.rs:+65:13: +65:14
+          scope 28 {
+              debug b => _45;              // in scope 28 at $DIR/reference_prop.rs:+65:13: +65:14
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+          StorageLive(_4);                 // scope 0 at $DIR/reference_prop.rs:+3:13: +3:18
+          _4 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+3:21: +3:28
+          StorageLive(_5);                 // scope 1 at $DIR/reference_prop.rs:+4:13: +4:14
+          _5 = &mut _4;                    // scope 1 at $DIR/reference_prop.rs:+4:17: +4:23
+          StorageLive(_6);                 // scope 2 at $DIR/reference_prop.rs:+5:13: +5:14
+-         _6 = (*_5);                      // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
+-         _3 = const ();                   // scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
++         _6 = _4;                         // scope 2 at $DIR/reference_prop.rs:+5:17: +5:19
+          StorageDead(_6);                 // scope 2 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_5);                 // scope 1 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_4);                 // scope 0 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageLive(_7);                 // scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageLive(_8);                 // scope 0 at $DIR/reference_prop.rs:+10:13: +10:18
+          _8 = const 5_usize;              // scope 0 at $DIR/reference_prop.rs:+10:21: +10:28
+          StorageLive(_9);                 // scope 4 at $DIR/reference_prop.rs:+11:13: +11:19
+          _9 = const 7_usize;              // scope 4 at $DIR/reference_prop.rs:+11:22: +11:29
+          StorageLive(_10);                // scope 5 at $DIR/reference_prop.rs:+12:13: +12:18
+          _10 = &mut _8;                   // scope 5 at $DIR/reference_prop.rs:+12:21: +12:27
+          StorageLive(_11);                // scope 6 at $DIR/reference_prop.rs:+13:13: +13:20
+-         StorageLive(_12);                // scope 6 at $DIR/reference_prop.rs:+13:13: +13:20
+-         _12 = &mut _9;                   // scope 6 at $DIR/reference_prop.rs:+13:13: +13:20
+-         _11 = &mut (*_12);               // scope 6 at $DIR/reference_prop.rs:+13:13: +13:20
++         _11 = &mut _9;                   // scope 6 at $DIR/reference_prop.rs:+13:13: +13:20
+          _10 = move _11;                  // scope 6 at $DIR/reference_prop.rs:+13:9: +13:20
+          StorageDead(_11);                // scope 6 at $DIR/reference_prop.rs:+13:19: +13:20
+-         StorageDead(_12);                // scope 6 at $DIR/reference_prop.rs:+13:20: +13:21
+          StorageLive(_13);                // scope 6 at $DIR/reference_prop.rs:+15:13: +15:14
+          _13 = (*_10);                    // scope 6 at $DIR/reference_prop.rs:+15:17: +15:19
+-         _7 = const ();                   // scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageDead(_13);                // scope 6 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_10);                // scope 5 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_9);                 // scope 4 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_8);                 // scope 0 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageDead(_7);                 // scope 0 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageLive(_14);                // scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+          StorageLive(_15);                // scope 0 at $DIR/reference_prop.rs:+20:13: +20:18
+          _15 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+20:21: +20:28
+          StorageLive(_16);                // scope 8 at $DIR/reference_prop.rs:+21:13: +21:14
+          _16 = &mut _15;                  // scope 8 at $DIR/reference_prop.rs:+21:17: +21:23
+          StorageLive(_17);                // scope 9 at $DIR/reference_prop.rs:+22:13: +22:14
+          _17 = &_16;                      // scope 9 at $DIR/reference_prop.rs:+22:17: +22:19
+          StorageLive(_18);                // scope 10 at $DIR/reference_prop.rs:+23:13: +23:14
+          _18 = (*_16);                    // scope 10 at $DIR/reference_prop.rs:+23:17: +23:19
+-         _14 = const ();                  // scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+          StorageDead(_18);                // scope 10 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_17);                // scope 9 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_16);                // scope 8 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_15);                // scope 0 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageDead(_14);                // scope 0 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageLive(_19);                // scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageLive(_20);                // scope 0 at $DIR/reference_prop.rs:+28:13: +28:18
+          _20 = const 5_usize;             // scope 0 at $DIR/reference_prop.rs:+28:21: +28:28
+          StorageLive(_21);                // scope 12 at $DIR/reference_prop.rs:+29:13: +29:18
+          _21 = &mut _20;                  // scope 12 at $DIR/reference_prop.rs:+29:21: +29:27
+          StorageLive(_22);                // scope 13 at $DIR/reference_prop.rs:+30:13: +30:14
+          _22 = &mut _21;                  // scope 13 at $DIR/reference_prop.rs:+30:17: +30:23
+          StorageLive(_23);                // scope 14 at $DIR/reference_prop.rs:+31:13: +31:14
+          _23 = (*_21);                    // scope 14 at $DIR/reference_prop.rs:+31:17: +31:19
+-         _19 = const ();                  // scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageDead(_23);                // scope 14 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_22);                // scope 13 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_21);                // scope 12 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_20);                // scope 0 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageDead(_19);                // scope 0 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageLive(_24);                // scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageLive(_25);                // scope 0 at $DIR/reference_prop.rs:+36:13: +36:18
+          _25 = const 7_usize;             // scope 0 at $DIR/reference_prop.rs:+36:21: +36:28
+          StorageLive(_26);                // scope 16 at $DIR/reference_prop.rs:+37:13: +37:14
+          _26 = &mut _25;                  // scope 16 at $DIR/reference_prop.rs:+37:17: +37:23
+          StorageLive(_27);                // scope 17 at $DIR/reference_prop.rs:+38:13: +38:14
+          _27 = (*_26);                    // scope 17 at $DIR/reference_prop.rs:+38:17: +38:19
+          StorageLive(_28);                // scope 18 at $DIR/reference_prop.rs:+39:9: +39:18
+          StorageLive(_29);                // scope 18 at $DIR/reference_prop.rs:+39:16: +39:17
+          _29 = move _26;                  // scope 18 at $DIR/reference_prop.rs:+39:16: +39:17
+          _28 = opaque::<&mut usize>(move _29) -> bb1; // scope 18 at $DIR/reference_prop.rs:+39:9: +39:18
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:117:9: 117:15
+                                           // + literal: Const { ty: fn(&mut usize) {opaque::<&mut usize>}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_29);                // scope 18 at $DIR/reference_prop.rs:+39:17: +39:18
+          StorageDead(_28);                // scope 18 at $DIR/reference_prop.rs:+39:18: +39:19
+-         _24 = const ();                  // scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageDead(_27);                // scope 17 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_26);                // scope 16 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_25);                // scope 0 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageDead(_24);                // scope 0 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageLive(_30);                // scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageLive(_31);                // scope 0 at $DIR/reference_prop.rs:+44:13: +44:18
+          _31 = const 7_usize;             // scope 0 at $DIR/reference_prop.rs:+44:21: +44:28
+          StorageLive(_32);                // scope 19 at $DIR/reference_prop.rs:+45:13: +45:15
+          _32 = &mut _31;                  // scope 19 at $DIR/reference_prop.rs:+45:18: +45:24
+          StorageLive(_33);                // scope 20 at $DIR/reference_prop.rs:+46:13: +46:14
+          _33 = (*_32);                    // scope 20 at $DIR/reference_prop.rs:+46:17: +46:20
+          StorageLive(_34);                // scope 21 at $DIR/reference_prop.rs:+47:13: +47:15
+          _34 = move _32;                  // scope 21 at $DIR/reference_prop.rs:+47:18: +47:20
+          StorageLive(_35);                // scope 22 at $DIR/reference_prop.rs:+48:13: +48:15
+          _35 = (*_34);                    // scope 22 at $DIR/reference_prop.rs:+48:18: +48:21
+          StorageLive(_36);                // scope 23 at $DIR/reference_prop.rs:+49:13: +49:15
+          _36 = move _34;                  // scope 23 at $DIR/reference_prop.rs:+49:18: +49:20
+          StorageLive(_37);                // scope 24 at $DIR/reference_prop.rs:+52:9: +52:19
+          StorageLive(_38);                // scope 24 at $DIR/reference_prop.rs:+52:16: +52:18
+          _38 = move _36;                  // scope 24 at $DIR/reference_prop.rs:+52:16: +52:18
+          _37 = opaque::<&mut usize>(move _38) -> bb2; // scope 24 at $DIR/reference_prop.rs:+52:9: +52:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:130:9: 130:15
+                                           // + literal: Const { ty: fn(&mut usize) {opaque::<&mut usize>}, val: Value(<ZST>) }
+      }
+  
+      bb2: {
+          StorageDead(_38);                // scope 24 at $DIR/reference_prop.rs:+52:18: +52:19
+          StorageDead(_37);                // scope 24 at $DIR/reference_prop.rs:+52:19: +52:20
+-         _30 = const ();                  // scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageDead(_36);                // scope 23 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_35);                // scope 22 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_34);                // scope 21 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_33);                // scope 20 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_32);                // scope 19 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_31);                // scope 0 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageDead(_30);                // scope 0 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageLive(_39);                // scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+          StorageLive(_40);                // scope 0 at $DIR/reference_prop.rs:+57:13: +57:14
+          _40 = &mut (*_1);                // scope 0 at $DIR/reference_prop.rs:+57:17: +57:29
+          StorageLive(_41);                // scope 25 at $DIR/reference_prop.rs:+58:13: +58:14
+-         _41 = (*_40);                    // scope 25 at $DIR/reference_prop.rs:+58:17: +58:19
+-         _39 = const ();                  // scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
++         _41 = (*_1);                     // scope 25 at $DIR/reference_prop.rs:+58:17: +58:19
+          StorageDead(_41);                // scope 25 at $DIR/reference_prop.rs:+59:5: +59:6
+          StorageDead(_40);                // scope 0 at $DIR/reference_prop.rs:+59:5: +59:6
+-         StorageDead(_39);                // scope 0 at $DIR/reference_prop.rs:+59:5: +59:6
+          StorageLive(_42);                // scope 0 at $DIR/reference_prop.rs:+63:13: +63:14
+          _42 = &mut (*_2);                // scope 0 at $DIR/reference_prop.rs:+63:17: +63:31
+          StorageLive(_43);                // scope 27 at $DIR/reference_prop.rs:+64:20: +64:32
+-         StorageLive(_44);                // scope 27 at $DIR/reference_prop.rs:+64:20: +64:32
+-         _44 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+64:20: +64:32
+-         _43 = &mut (*_44);               // scope 27 at $DIR/reference_prop.rs:+64:20: +64:32
++         _43 = &mut (*_1);                // scope 27 at $DIR/reference_prop.rs:+64:20: +64:32
+          _2 = move _43;                   // scope 27 at $DIR/reference_prop.rs:+64:9: +64:32
+          StorageDead(_43);                // scope 27 at $DIR/reference_prop.rs:+64:31: +64:32
+-         StorageDead(_44);                // scope 27 at $DIR/reference_prop.rs:+64:32: +64:33
+          StorageLive(_45);                // scope 27 at $DIR/reference_prop.rs:+65:13: +65:14
+          _45 = (*_42);                    // scope 27 at $DIR/reference_prop.rs:+65:17: +65:19
+          _0 = const ();                   // scope 0 at $DIR/reference_prop.rs:+62:5: +66:6
+          StorageDead(_45);                // scope 27 at $DIR/reference_prop.rs:+66:5: +66:6
+          StorageDead(_42);                // scope 0 at $DIR/reference_prop.rs:+66:5: +66:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+67:2: +67:2
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
new file mode 100644
index 00000000000..235964e9536
--- /dev/null
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
@@ -0,0 +1,294 @@
+- // MIR for `reference_propagation_mut_ptr` before ReferencePropagation
++ // MIR for `reference_propagation_mut_ptr` after ReferencePropagation
+  
+  fn reference_propagation_mut_ptr(_1: *mut T, _2: *mut T) -> () {
+      debug single => _1;                  // in scope 0 at $DIR/reference_prop.rs:+0:43: +0:49
+      debug multiple => _2;                // in scope 0 at $DIR/reference_prop.rs:+0:59: +0:71
+      let mut _0: ();                      // return place in scope 0 at $DIR/reference_prop.rs:+0:81: +0:81
+      let _3: ();                          // in scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+      let _7: ();                          // in scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+      let mut _11: *mut usize;             // in scope 0 at $DIR/reference_prop.rs:+13:13: +13:24
+      let _13: ();                         // in scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+      let _18: ();                         // in scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+      let _23: ();                         // in scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+      let _27: ();                         // in scope 0 at $DIR/reference_prop.rs:+39:9: +39:18
+      let mut _28: *mut usize;             // in scope 0 at $DIR/reference_prop.rs:+39:16: +39:17
+      let _29: ();                         // in scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+      let _36: ();                         // in scope 0 at $DIR/reference_prop.rs:+52:9: +52:19
+      let mut _37: *mut usize;             // in scope 0 at $DIR/reference_prop.rs:+52:16: +52:18
+      let _38: ();                         // in scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+      let mut _42: *mut T;                 // in scope 0 at $DIR/reference_prop.rs:+64:20: +64:36
+      scope 1 {
+          let mut _4: usize;               // in scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
+          scope 2 {
+              debug a => _4;               // in scope 2 at $DIR/reference_prop.rs:+3:13: +3:18
+              let _5: *mut usize;          // in scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+              scope 3 {
+                  debug b => _5;           // in scope 3 at $DIR/reference_prop.rs:+4:13: +4:14
+                  let _6: usize;           // in scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
+                  scope 4 {
+                      debug c => _6;       // in scope 4 at $DIR/reference_prop.rs:+5:13: +5:14
+                  }
+              }
+          }
+      }
+      scope 5 {
+          let mut _8: usize;               // in scope 5 at $DIR/reference_prop.rs:+10:13: +10:18
+          scope 6 {
+              debug a => _8;               // in scope 6 at $DIR/reference_prop.rs:+10:13: +10:18
+              let mut _9: usize;           // in scope 6 at $DIR/reference_prop.rs:+11:13: +11:19
+              scope 7 {
+                  debug a2 => _9;          // in scope 7 at $DIR/reference_prop.rs:+11:13: +11:19
+                  let mut _10: *mut usize; // in scope 7 at $DIR/reference_prop.rs:+12:13: +12:18
+                  scope 8 {
+                      debug b => _10;      // in scope 8 at $DIR/reference_prop.rs:+12:13: +12:18
+                      let _12: usize;      // in scope 8 at $DIR/reference_prop.rs:+15:13: +15:14
+                      scope 9 {
+                          debug c => _12;  // in scope 9 at $DIR/reference_prop.rs:+15:13: +15:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 10 {
+          let mut _14: usize;              // in scope 10 at $DIR/reference_prop.rs:+20:13: +20:18
+          scope 11 {
+              debug a => _14;              // in scope 11 at $DIR/reference_prop.rs:+20:13: +20:18
+              let _15: *mut usize;         // in scope 11 at $DIR/reference_prop.rs:+21:13: +21:14
+              scope 12 {
+                  debug b => _15;          // in scope 12 at $DIR/reference_prop.rs:+21:13: +21:14
+                  let _16: &*mut usize;    // in scope 12 at $DIR/reference_prop.rs:+22:13: +22:14
+                  scope 13 {
+                      debug d => _16;      // in scope 13 at $DIR/reference_prop.rs:+22:13: +22:14
+                      let _17: usize;      // in scope 13 at $DIR/reference_prop.rs:+23:13: +23:14
+                      scope 14 {
+                          debug c => _17;  // in scope 14 at $DIR/reference_prop.rs:+23:13: +23:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 15 {
+          let mut _19: usize;              // in scope 15 at $DIR/reference_prop.rs:+28:13: +28:18
+          scope 16 {
+              debug a => _19;              // in scope 16 at $DIR/reference_prop.rs:+28:13: +28:18
+              let mut _20: *mut usize;     // in scope 16 at $DIR/reference_prop.rs:+29:13: +29:18
+              scope 17 {
+                  debug b => _20;          // in scope 17 at $DIR/reference_prop.rs:+29:13: +29:18
+                  let _21: &mut *mut usize; // in scope 17 at $DIR/reference_prop.rs:+30:13: +30:14
+                  scope 18 {
+                      debug d => _21;      // in scope 18 at $DIR/reference_prop.rs:+30:13: +30:14
+                      let _22: usize;      // in scope 18 at $DIR/reference_prop.rs:+31:13: +31:14
+                      scope 19 {
+                          debug c => _22;  // in scope 19 at $DIR/reference_prop.rs:+31:13: +31:14
+                      }
+                  }
+              }
+          }
+      }
+      scope 20 {
+          let mut _24: usize;              // in scope 20 at $DIR/reference_prop.rs:+36:13: +36:18
+          scope 21 {
+              debug a => _24;              // in scope 21 at $DIR/reference_prop.rs:+36:13: +36:18
+              let _25: *mut usize;         // in scope 21 at $DIR/reference_prop.rs:+37:13: +37:14
+              scope 22 {
+                  debug b => _25;          // in scope 22 at $DIR/reference_prop.rs:+37:13: +37:14
+                  let _26: usize;          // in scope 22 at $DIR/reference_prop.rs:+38:13: +38:14
+                  scope 23 {
+                      debug c => _26;      // in scope 23 at $DIR/reference_prop.rs:+38:13: +38:14
+                  }
+              }
+          }
+      }
+      scope 24 {
+          let mut _30: usize;              // in scope 24 at $DIR/reference_prop.rs:+44:13: +44:18
+          scope 25 {
+              debug a => _30;              // in scope 25 at $DIR/reference_prop.rs:+44:13: +44:18
+              let _31: *mut usize;         // in scope 25 at $DIR/reference_prop.rs:+45:13: +45:15
+              scope 26 {
+                  debug b1 => _31;         // in scope 26 at $DIR/reference_prop.rs:+45:13: +45:15
+                  let _32: usize;          // in scope 26 at $DIR/reference_prop.rs:+46:13: +46:14
+                  scope 27 {
+                      debug c => _32;      // in scope 27 at $DIR/reference_prop.rs:+46:13: +46:14
+                      let _33: *mut usize; // in scope 27 at $DIR/reference_prop.rs:+47:13: +47:15
+                      scope 28 {
+                          debug b2 => _33; // in scope 28 at $DIR/reference_prop.rs:+47:13: +47:15
+                          let _34: usize;  // in scope 28 at $DIR/reference_prop.rs:+48:13: +48:15
+                          scope 29 {
+                              debug c2 => _34; // in scope 29 at $DIR/reference_prop.rs:+48:13: +48:15
+                              let _35: *mut usize; // in scope 29 at $DIR/reference_prop.rs:+49:13: +49:15
+                              scope 30 {
+                                  debug b3 => _35; // in scope 30 at $DIR/reference_prop.rs:+49:13: +49:15
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+      scope 31 {
+          let _39: *mut T;                 // in scope 31 at $DIR/reference_prop.rs:+57:13: +57:14
+          scope 32 {
+              debug a => _39;              // in scope 32 at $DIR/reference_prop.rs:+57:13: +57:14
+              let _40: T;                  // in scope 32 at $DIR/reference_prop.rs:+58:13: +58:14
+              scope 33 {
+                  debug b => _40;          // in scope 33 at $DIR/reference_prop.rs:+58:13: +58:14
+              }
+          }
+      }
+      scope 34 {
+          let _41: *mut T;                 // in scope 34 at $DIR/reference_prop.rs:+63:13: +63:14
+          scope 35 {
+              debug a => _41;              // in scope 35 at $DIR/reference_prop.rs:+63:13: +63:14
+              let _43: T;                  // in scope 35 at $DIR/reference_prop.rs:+65:13: +65:14
+              scope 36 {
+                  debug b => _43;          // in scope 36 at $DIR/reference_prop.rs:+65:13: +65:14
+              }
+          }
+      }
+  
+      bb0: {
+-         StorageLive(_3);                 // scope 0 at $DIR/reference_prop.rs:+2:5: +6:6
+          StorageLive(_4);                 // scope 1 at $DIR/reference_prop.rs:+3:13: +3:18
+          _4 = const 5_usize;              // scope 1 at $DIR/reference_prop.rs:+3:21: +3:28
+          StorageLive(_5);                 // scope 2 at $DIR/reference_prop.rs:+4:13: +4:14
+          _5 = &raw mut _4;                // scope 2 at $DIR/reference_prop.rs:+4:17: +4:27
+          StorageLive(_6);                 // scope 3 at $DIR/reference_prop.rs:+5:13: +5:14
+-         _6 = (*_5);                      // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
+-         _3 = const ();                   // scope 1 at $DIR/reference_prop.rs:+2:5: +6:6
++         _6 = _4;                         // scope 3 at $DIR/reference_prop.rs:+5:17: +5:19
+          StorageDead(_6);                 // scope 3 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_5);                 // scope 2 at $DIR/reference_prop.rs:+6:5: +6:6
+          StorageDead(_4);                 // scope 1 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageDead(_3);                 // scope 0 at $DIR/reference_prop.rs:+6:5: +6:6
+-         StorageLive(_7);                 // scope 0 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageLive(_8);                 // scope 5 at $DIR/reference_prop.rs:+10:13: +10:18
+          _8 = const 5_usize;              // scope 5 at $DIR/reference_prop.rs:+10:21: +10:28
+          StorageLive(_9);                 // scope 6 at $DIR/reference_prop.rs:+11:13: +11:19
+          _9 = const 7_usize;              // scope 6 at $DIR/reference_prop.rs:+11:22: +11:29
+          StorageLive(_10);                // scope 7 at $DIR/reference_prop.rs:+12:13: +12:18
+          _10 = &raw mut _8;               // scope 7 at $DIR/reference_prop.rs:+12:21: +12:31
+          StorageLive(_11);                // scope 8 at $DIR/reference_prop.rs:+13:13: +13:24
+          _11 = &raw mut _9;               // scope 8 at $DIR/reference_prop.rs:+13:13: +13:24
+          _10 = move _11;                  // scope 8 at $DIR/reference_prop.rs:+13:9: +13:24
+          StorageDead(_11);                // scope 8 at $DIR/reference_prop.rs:+13:23: +13:24
+          StorageLive(_12);                // scope 8 at $DIR/reference_prop.rs:+15:13: +15:14
+          _12 = (*_10);                    // scope 8 at $DIR/reference_prop.rs:+15:17: +15:19
+-         _7 = const ();                   // scope 5 at $DIR/reference_prop.rs:+9:5: +16:6
+          StorageDead(_12);                // scope 8 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_10);                // scope 7 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_9);                 // scope 6 at $DIR/reference_prop.rs:+16:5: +16:6
+          StorageDead(_8);                 // scope 5 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageDead(_7);                 // scope 0 at $DIR/reference_prop.rs:+16:5: +16:6
+-         StorageLive(_13);                // scope 0 at $DIR/reference_prop.rs:+19:5: +24:6
+          StorageLive(_14);                // scope 10 at $DIR/reference_prop.rs:+20:13: +20:18
+          _14 = const 5_usize;             // scope 10 at $DIR/reference_prop.rs:+20:21: +20:28
+          StorageLive(_15);                // scope 11 at $DIR/reference_prop.rs:+21:13: +21:14
+          _15 = &raw mut _14;              // scope 11 at $DIR/reference_prop.rs:+21:17: +21:27
+          StorageLive(_16);                // scope 12 at $DIR/reference_prop.rs:+22:13: +22:14
+          _16 = &_15;                      // scope 12 at $DIR/reference_prop.rs:+22:17: +22:19
+          StorageLive(_17);                // scope 13 at $DIR/reference_prop.rs:+23:13: +23:14
+          _17 = (*_15);                    // scope 13 at $DIR/reference_prop.rs:+23:17: +23:19
+-         _13 = const ();                  // scope 10 at $DIR/reference_prop.rs:+19:5: +24:6
+          StorageDead(_17);                // scope 13 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_16);                // scope 12 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_15);                // scope 11 at $DIR/reference_prop.rs:+24:5: +24:6
+          StorageDead(_14);                // scope 10 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageDead(_13);                // scope 0 at $DIR/reference_prop.rs:+24:5: +24:6
+-         StorageLive(_18);                // scope 0 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageLive(_19);                // scope 15 at $DIR/reference_prop.rs:+28:13: +28:18
+          _19 = const 5_usize;             // scope 15 at $DIR/reference_prop.rs:+28:21: +28:28
+          StorageLive(_20);                // scope 16 at $DIR/reference_prop.rs:+29:13: +29:18
+          _20 = &raw mut _19;              // scope 16 at $DIR/reference_prop.rs:+29:21: +29:31
+          StorageLive(_21);                // scope 17 at $DIR/reference_prop.rs:+30:13: +30:14
+          _21 = &mut _20;                  // scope 17 at $DIR/reference_prop.rs:+30:17: +30:23
+          StorageLive(_22);                // scope 18 at $DIR/reference_prop.rs:+31:13: +31:14
+          _22 = (*_20);                    // scope 18 at $DIR/reference_prop.rs:+31:17: +31:19
+-         _18 = const ();                  // scope 15 at $DIR/reference_prop.rs:+27:5: +32:6
+          StorageDead(_22);                // scope 18 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_21);                // scope 17 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_20);                // scope 16 at $DIR/reference_prop.rs:+32:5: +32:6
+          StorageDead(_19);                // scope 15 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageDead(_18);                // scope 0 at $DIR/reference_prop.rs:+32:5: +32:6
+-         StorageLive(_23);                // scope 0 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageLive(_24);                // scope 20 at $DIR/reference_prop.rs:+36:13: +36:18
+          _24 = const 7_usize;             // scope 20 at $DIR/reference_prop.rs:+36:21: +36:28
+          StorageLive(_25);                // scope 21 at $DIR/reference_prop.rs:+37:13: +37:14
+          _25 = &raw mut _24;              // scope 21 at $DIR/reference_prop.rs:+37:17: +37:27
+          StorageLive(_26);                // scope 22 at $DIR/reference_prop.rs:+38:13: +38:14
+          _26 = (*_25);                    // scope 22 at $DIR/reference_prop.rs:+38:17: +38:19
+          StorageLive(_27);                // scope 23 at $DIR/reference_prop.rs:+39:9: +39:18
+          StorageLive(_28);                // scope 23 at $DIR/reference_prop.rs:+39:16: +39:17
+          _28 = _25;                       // scope 23 at $DIR/reference_prop.rs:+39:16: +39:17
+          _27 = opaque::<*mut usize>(move _28) -> bb1; // scope 23 at $DIR/reference_prop.rs:+39:9: +39:18
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:263:9: 263:15
+                                           // + literal: Const { ty: fn(*mut usize) {opaque::<*mut usize>}, val: Value(<ZST>) }
+      }
+  
+      bb1: {
+          StorageDead(_28);                // scope 23 at $DIR/reference_prop.rs:+39:17: +39:18
+          StorageDead(_27);                // scope 23 at $DIR/reference_prop.rs:+39:18: +39:19
+-         _23 = const ();                  // scope 20 at $DIR/reference_prop.rs:+35:5: +40:6
+          StorageDead(_26);                // scope 22 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_25);                // scope 21 at $DIR/reference_prop.rs:+40:5: +40:6
+          StorageDead(_24);                // scope 20 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageDead(_23);                // scope 0 at $DIR/reference_prop.rs:+40:5: +40:6
+-         StorageLive(_29);                // scope 0 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageLive(_30);                // scope 24 at $DIR/reference_prop.rs:+44:13: +44:18
+          _30 = const 7_usize;             // scope 24 at $DIR/reference_prop.rs:+44:21: +44:28
+          StorageLive(_31);                // scope 25 at $DIR/reference_prop.rs:+45:13: +45:15
+          _31 = &raw mut _30;              // scope 25 at $DIR/reference_prop.rs:+45:18: +45:28
+          StorageLive(_32);                // scope 26 at $DIR/reference_prop.rs:+46:13: +46:14
+          _32 = (*_31);                    // scope 26 at $DIR/reference_prop.rs:+46:17: +46:20
+          StorageLive(_33);                // scope 27 at $DIR/reference_prop.rs:+47:13: +47:15
+          _33 = _31;                       // scope 27 at $DIR/reference_prop.rs:+47:18: +47:20
+          StorageLive(_34);                // scope 28 at $DIR/reference_prop.rs:+48:13: +48:15
+          _34 = (*_33);                    // scope 28 at $DIR/reference_prop.rs:+48:18: +48:21
+          StorageLive(_35);                // scope 29 at $DIR/reference_prop.rs:+49:13: +49:15
+          _35 = _33;                       // scope 29 at $DIR/reference_prop.rs:+49:18: +49:20
+          StorageLive(_36);                // scope 30 at $DIR/reference_prop.rs:+52:9: +52:19
+          StorageLive(_37);                // scope 30 at $DIR/reference_prop.rs:+52:16: +52:18
+          _37 = _35;                       // scope 30 at $DIR/reference_prop.rs:+52:16: +52:18
+          _36 = opaque::<*mut usize>(move _37) -> bb2; // scope 30 at $DIR/reference_prop.rs:+52:9: +52:19
+                                           // mir::Constant
+                                           // + span: $DIR/reference_prop.rs:276:9: 276:15
+                                           // + literal: Const { ty: fn(*mut usize) {opaque::<*mut usize>}, val: Value(<ZST>) }
+      }
+  
+      bb2: {
+          StorageDead(_37);                // scope 30 at $DIR/reference_prop.rs:+52:18: +52:19
+          StorageDead(_36);                // scope 30 at $DIR/reference_prop.rs:+52:19: +52:20
+-         _29 = const ();                  // scope 24 at $DIR/reference_prop.rs:+43:5: +53:6
+          StorageDead(_35);                // scope 29 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_34);                // scope 28 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_33);                // scope 27 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_32);                // scope 26 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_31);                // scope 25 at $DIR/reference_prop.rs:+53:5: +53:6
+          StorageDead(_30);                // scope 24 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageDead(_29);                // scope 0 at $DIR/reference_prop.rs:+53:5: +53:6
+-         StorageLive(_38);                // scope 0 at $DIR/reference_prop.rs:+56:5: +59:6
+          StorageLive(_39);                // scope 31 at $DIR/reference_prop.rs:+57:13: +57:14
+          _39 = &raw mut (*_1);            // scope 31 at $DIR/reference_prop.rs:+57:17: +57:33
+          StorageLive(_40);                // scope 32 at $DIR/reference_prop.rs:+58:13: +58:14
+-         _40 = (*_39);                    // scope 32 at $DIR/reference_prop.rs:+58:17: +58:19
+-         _38 = const ();                  // scope 31 at $DIR/reference_prop.rs:+56:5: +59:6
++         _40 = (*_1);                     // scope 32 at $DIR/reference_prop.rs:+58:17: +58:19
+          StorageDead(_40);                // scope 32 at $DIR/reference_prop.rs:+59:5: +59:6
+          StorageDead(_39);                // scope 31 at $DIR/reference_prop.rs:+59:5: +59:6
+-         StorageDead(_38);                // scope 0 at $DIR/reference_prop.rs:+59:5: +59:6
+          StorageLive(_41);                // scope 34 at $DIR/reference_prop.rs:+63:13: +63:14
+          _41 = &raw mut (*_2);            // scope 34 at $DIR/reference_prop.rs:+63:17: +63:35
+          StorageLive(_42);                // scope 35 at $DIR/reference_prop.rs:+64:20: +64:36
+          _42 = &raw mut (*_1);            // scope 35 at $DIR/reference_prop.rs:+64:20: +64:36
+          _2 = move _42;                   // scope 35 at $DIR/reference_prop.rs:+64:9: +64:36
+          StorageDead(_42);                // scope 35 at $DIR/reference_prop.rs:+64:35: +64:36
+          StorageLive(_43);                // scope 35 at $DIR/reference_prop.rs:+65:13: +65:14
+          _43 = (*_41);                    // scope 35 at $DIR/reference_prop.rs:+65:17: +65:19
+          _0 = const ();                   // scope 34 at $DIR/reference_prop.rs:+62:5: +66:6
+          StorageDead(_43);                // scope 35 at $DIR/reference_prop.rs:+66:5: +66:6
+          StorageDead(_41);                // scope 34 at $DIR/reference_prop.rs:+66:5: +66:6
+          return;                          // scope 0 at $DIR/reference_prop.rs:+67:2: +67:2
+      }
+  }
+  
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
new file mode 100644
index 00000000000..5625c20a420
--- /dev/null
+++ b/tests/mir-opt/reference_prop.rs
@@ -0,0 +1,428 @@
+// unit-test: ReferencePropagation
+
+#![feature(raw_ref_op)]
+#![feature(core_intrinsics, custom_mir)]
+
+#[inline(never)]
+fn opaque(_: impl Sized) {}
+
+fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) {
+    // Propagation through a reference.
+    {
+        let a = 5_usize;
+        let b = &a; // This borrow is only used once.
+        let c = *b; // This should be optimized.
+    }
+
+    // Propagation through a two references.
+    {
+        let a = 5_usize;
+        let a2 = 7_usize;
+        let mut b = &a;
+        b = &a2;
+        // `b` is assigned twice, so we cannot propagate it.
+        let c = *b;
+    }
+
+    // Propagation through a borrowed reference.
+    {
+        let a = 5_usize;
+        let b = &a;
+        let d = &b;
+        let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
+    }
+
+    // Propagation through a borrowed reference.
+    {
+        let a = 5_usize;
+        let mut b = &a;
+        let d = &mut b;
+        let c = *b; // `b` is mutably borrowed, we cannot know its value.
+    }
+
+    // Propagation through an escaping borrow.
+    {
+        let a = 7_usize;
+        let b = &a;
+        let c = *b;
+        opaque(b); // `b` escapes here, so we can only replace immutable borrow
+    }
+
+    // Propagation through a transitively escaping borrow.
+    {
+        let a = 7_usize;
+        let b1 = &a;
+        let c = *b1;
+        let b2 = b1;
+        let c2 = *b2;
+        let b3 = b2;
+        // `b3` escapes here, so we can only replace immutable borrow,
+        // for either `b`, `b2` or `b3`.
+        opaque(b3);
+    }
+
+    // Propagation a reborrow of an argument.
+    {
+        let a = &*single;
+        let b = *a; // This should be optimized as `*single`.
+    }
+
+    // Propagation a reborrow of a mutated argument.
+    {
+        let a = &*multiple;
+        multiple = &*single;
+        let b = *a; // This should not be optimized.
+    }
+}
+
+fn reference_propagation_mut<'a, T: Copy>(single: &'a mut T, mut multiple: &'a mut T) {
+    // Propagation through a reference.
+    {
+        let mut a = 5_usize;
+        let b = &mut a; // This borrow is only used once.
+        let c = *b; // This should be optimized.
+    }
+
+    // Propagation through a two references.
+    {
+        let mut a = 5_usize;
+        let mut a2 = 7_usize;
+        let mut b = &mut a;
+        b = &mut a2;
+        // `b` is assigned twice, so we cannot propagate it.
+        let c = *b;
+    }
+
+    // Propagation through a borrowed reference.
+    {
+        let mut a = 5_usize;
+        let b = &mut a;
+        let d = &b;
+        let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
+    }
+
+    // Propagation through a borrowed reference.
+    {
+        let mut a = 5_usize;
+        let mut b = &mut a;
+        let d = &mut b;
+        let c = *b; // `b` is mutably borrowed, we cannot know its value.
+    }
+
+    // Propagation through an escaping borrow.
+    {
+        let mut a = 7_usize;
+        let b = &mut a;
+        let c = *b;
+        opaque(b); // `b` escapes here, so we can only replace immutable borrow
+    }
+
+    // Propagation through a transitively escaping borrow.
+    {
+        let mut a = 7_usize;
+        let b1 = &mut a;
+        let c = *b1;
+        let b2 = b1;
+        let c2 = *b2;
+        let b3 = b2;
+        // `b3` escapes here, so we can only replace immutable borrow,
+        // for either `b`, `b2` or `b3`.
+        opaque(b3);
+    }
+
+    // Propagation a reborrow of an argument.
+    {
+        let a = &mut *single;
+        let b = *a; // This should be optimized as `*single`.
+    }
+
+    // Propagation a reborrow of a mutated argument.
+    {
+        let a = &mut *multiple;
+        multiple = &mut *single;
+        let b = *a; // This should not be optimized.
+    }
+}
+
+fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *const T) {
+    // Propagation through a reference.
+    unsafe {
+        let a = 5_usize;
+        let b = &raw const a; // This borrow is only used once.
+        let c = *b; // This should be optimized.
+    }
+
+    // Propagation through a two references.
+    unsafe {
+        let a = 5_usize;
+        let a2 = 7_usize;
+        let mut b = &raw const a;
+        b = &raw const a2;
+        // `b` is assigned twice, so we cannot propagate it.
+        let c = *b;
+    }
+
+    // Propagation through a borrowed reference.
+    unsafe {
+        let a = 5_usize;
+        let b = &raw const a;
+        let d = &b;
+        let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
+    }
+
+    // Propagation through a borrowed reference.
+    unsafe {
+        let a = 5_usize;
+        let mut b = &raw const a;
+        let d = &mut b;
+        let c = *b; // `b` is mutably borrowed, we cannot know its value.
+    }
+
+    // Propagation through an escaping borrow.
+    unsafe {
+        let a = 7_usize;
+        let b = &raw const a;
+        let c = *b;
+        opaque(b); // `b` escapes here, so we can only replace immutable borrow
+    }
+
+    // Propagation through a transitively escaping borrow.
+    unsafe {
+        let a = 7_usize;
+        let b1 = &raw const a;
+        let c = *b1;
+        let b2 = b1;
+        let c2 = *b2;
+        let b3 = b2;
+        // `b3` escapes here, so we can only replace immutable borrow,
+        // for either `b`, `b2` or `b3`.
+        opaque(b3);
+    }
+
+    // Propagation a reborrow of an argument.
+    unsafe {
+        let a = &raw const *single;
+        let b = *a; // This should be optimized as `*single`.
+    }
+
+    // Propagation a reborrow of a mutated argument.
+    unsafe {
+        let a = &raw const *multiple;
+        multiple = &raw const *single;
+        let b = *a; // This should not be optimized.
+    }
+
+    // Propagation through a reborrow.
+    unsafe {
+        let a = 13_usize;
+        let b = &raw const a;
+        let c = &raw const *b;
+        let e = *c;
+    }
+}
+
+fn reference_propagation_mut_ptr<T: Copy>(single: *mut T, mut multiple: *mut T) {
+    // Propagation through a reference.
+    unsafe {
+        let mut a = 5_usize;
+        let b = &raw mut a; // This borrow is only used once.
+        let c = *b; // This should be optimized.
+    }
+
+    // Propagation through a two references.
+    unsafe {
+        let mut a = 5_usize;
+        let mut a2 = 7_usize;
+        let mut b = &raw mut a;
+        b = &raw mut a2;
+        // `b` is assigned twice, so we cannot propagate it.
+        let c = *b;
+    }
+
+    // Propagation through a borrowed reference.
+    unsafe {
+        let mut a = 5_usize;
+        let b = &raw mut a;
+        let d = &b;
+        let c = *b; // `b` is immutably borrowed, we know its value, but cannot be removed.
+    }
+
+    // Propagation through a borrowed reference.
+    unsafe {
+        let mut a = 5_usize;
+        let mut b = &raw mut a;
+        let d = &mut b;
+        let c = *b; // `b` is mutably borrowed, we cannot know its value.
+    }
+
+    // Propagation through an escaping borrow.
+    unsafe {
+        let mut a = 7_usize;
+        let b = &raw mut a;
+        let c = *b;
+        opaque(b); // `b` escapes here, so we can only replace immutable borrow
+    }
+
+    // Propagation through a transitively escaping borrow.
+    unsafe {
+        let mut a = 7_usize;
+        let b1 = &raw mut a;
+        let c = *b1;
+        let b2 = b1;
+        let c2 = *b2;
+        let b3 = b2;
+        // `b3` escapes here, so we can only replace immutable borrow,
+        // for either `b`, `b2` or `b3`.
+        opaque(b3);
+    }
+
+    // Propagation a reborrow of an argument.
+    unsafe {
+        let a = &raw mut *single;
+        let b = *a; // This should be optimized as `*single`.
+    }
+
+    // Propagation a reborrow of a mutated argument.
+    unsafe {
+        let a = &raw mut *multiple;
+        multiple = &raw mut *single;
+        let b = *a; // This should not be optimized.
+    }
+}
+
+#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
+fn read_through_raw(x: &mut usize) -> usize {
+    use std::intrinsics::mir::*;
+
+    mir!(
+        let r1: &mut usize;
+        let r2: &mut usize;
+        let p1: *mut usize;
+        let p2: *mut usize;
+
+        {
+            r1 = &mut *x;
+            r2 = &mut *r1;
+            p1 = &raw mut *r1;
+            p2 = &raw mut *r2;
+
+            RET = *p1;
+            RET = *p2;
+            Return()
+        }
+    )
+}
+
+#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
+fn multiple_storage() {
+    use std::intrinsics::mir::*;
+
+    mir!(
+        let x: i32;
+        {
+            StorageLive(x);
+            x = 5;
+            let z = &x;
+            StorageDead(x);
+            StorageLive(x);
+            // As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s
+            // pointer address is the address of `x`, so do nothing.
+            let y = *z;
+            Call(RET, retblock, opaque(y))
+        }
+
+        retblock = {
+            Return()
+        }
+    )
+}
+
+#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
+fn dominate_storage() {
+    use std::intrinsics::mir::*;
+
+    mir!(
+        let x: i32;
+        let r: &i32;
+        let c: i32;
+        let d: bool;
+        { Goto(bb0) }
+        bb0 = {
+            x = 5;
+            r = &x;
+            Goto(bb1)
+        }
+        bb1 = {
+            let c = *r;
+            Call(RET, bb2, opaque(c))
+        }
+        bb2 = {
+            StorageDead(x);
+            StorageLive(x);
+            let d = true;
+            match d { false => bb2, _ => bb0 }
+        }
+    )
+}
+
+#[custom_mir(dialect = "runtime", phase = "post-cleanup")]
+fn maybe_dead(m: bool) {
+    use std::intrinsics::mir::*;
+
+    mir!(
+        let x: i32;
+        let y: i32;
+        {
+            StorageLive(x);
+            StorageLive(y);
+            x = 5;
+            y = 5;
+            let a = &x;
+            let b = &mut y;
+            // As we don't replace `b` in `bb2`, we cannot replace it here either.
+            *b = 7;
+            match m { true => bb1, _ => bb2 }
+        }
+        bb1 = {
+            StorageDead(x);
+            StorageDead(y);
+            Goto(bb2)
+        }
+        bb2 = {
+            // As `x` may be `StorageDead`, `a` may be dangling, so we do nothing.
+            let z = *a;
+            Call(RET, bb3, opaque(z))
+        }
+        bb3 = {
+            // As `y` may be `StorageDead`, `b` may be dangling, so we do nothing.
+            // This implies that we also do not substitute `b` in `bb0`.
+            let t = *b;
+            Call(RET, retblock, opaque(t))
+        }
+        retblock = {
+            Return()
+        }
+    )
+}
+
+fn main() {
+    let mut x = 5_usize;
+    let mut y = 7_usize;
+    reference_propagation(&x, &y);
+    reference_propagation_mut(&mut x, &mut y);
+    reference_propagation_const_ptr(&raw const x, &raw const y);
+    reference_propagation_mut_ptr(&raw mut x, &raw mut y);
+    read_through_raw(&mut x);
+    multiple_storage();
+    dominate_storage();
+    maybe_dead(true);
+}
+
+// EMIT_MIR reference_prop.reference_propagation.ReferencePropagation.diff
+// EMIT_MIR reference_prop.reference_propagation_mut.ReferencePropagation.diff
+// EMIT_MIR reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
+// EMIT_MIR reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
+// EMIT_MIR reference_prop.read_through_raw.ReferencePropagation.diff
+// EMIT_MIR reference_prop.multiple_storage.ReferencePropagation.diff
+// EMIT_MIR reference_prop.dominate_storage.ReferencePropagation.diff
+// EMIT_MIR reference_prop.maybe_dead.ReferencePropagation.diff
diff --git a/tests/mir-opt/slice_filter.rs b/tests/mir-opt/slice_filter.rs
index 97c18af31de..be32f40f132 100644
--- a/tests/mir-opt/slice_filter.rs
+++ b/tests/mir-opt/slice_filter.rs
@@ -12,7 +12,9 @@ pub fn variant_b(input: &[(usize, usize, usize, usize)]) -> usize {
     input.iter().filter(|&&(a, b, c, d)| a <= c && d <= b || c <= a && b <= d).count()
 }
 
+// EMIT_MIR slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
 // EMIT_MIR slice_filter.variant_a-{closure#0}.CopyProp.diff
 // EMIT_MIR slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
 // EMIT_MIR slice_filter.variant_b-{closure#0}.CopyProp.diff
+// EMIT_MIR slice_filter.variant_b-{closure#0}.ReferencePropagation.diff
 // EMIT_MIR slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
index 294c3272f4f..a81553733a7 100644
--- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
+++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
@@ -30,10 +30,14 @@
       let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
       let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
       scope 1 {
-          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+-         debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+-         debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+-         debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+-         debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
++         debug a => _20;                  // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
++         debug b => _15;                  // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
++         debug c => _11;                  // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
++         debug d => _24;                  // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
           scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
               debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
               debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
@@ -86,24 +90,29 @@
   
       bb0: {
           _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+-         _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
++         _20 = &((*_25).0: usize);        // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
           _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+-         _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
++         _15 = &((*_26).1: usize);        // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
           _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+-         _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
++         _11 = &((*_27).2: usize);        // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
           _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+-         _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
 -         StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
++         _24 = &((*_28).3: usize);        // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
           StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
           StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
           StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _29 = deref_copy (*_9);          // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _30 = deref_copy (*_10);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         _29 = deref_copy _3;             // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
++         _29 = deref_copy _20;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _30 = deref_copy _11;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_31);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _31 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_32);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
@@ -111,7 +120,8 @@
           _8 = Le(move _31, move _32);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_32);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_31);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
           StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
           StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
           switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
@@ -127,13 +137,14 @@
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
           StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
           StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
           StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _33 = deref_copy (*_18);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _34 = deref_copy (*_19);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         _33 = deref_copy _5;             // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
++         _33 = deref_copy _11;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _34 = deref_copy _20;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_35);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _35 = (*_33);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_36);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
@@ -141,7 +152,8 @@
           _17 = Le(move _35, move _36);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_36);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_35);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
           StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
           StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
           switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
@@ -166,13 +178,14 @@
 -         StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
           StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
           StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _37 = deref_copy (*_13);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _38 = deref_copy (*_14);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         _37 = deref_copy _6;             // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
++         _37 = deref_copy _24;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _38 = deref_copy _15;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_39);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _39 = (*_37);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_40);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
@@ -180,7 +193,8 @@
           _12 = Le(move _39, move _40);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_40);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_39);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
           StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
 -         _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
@@ -202,13 +216,14 @@
 -         StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
 +         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
           StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
           StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _41 = deref_copy (*_22);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _42 = deref_copy (*_23);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _41 = deref_copy _4;             // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
++         _41 = deref_copy _15;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _42 = deref_copy _24;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           _43 = (*_41);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageLive(_44);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
@@ -217,7 +232,8 @@
 +         _0 = Le(move _43, move _44);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_44);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
           StorageDead(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
++         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
           StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
           StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
 -         _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
new file mode 100644
index 00000000000..18ea7305954
--- /dev/null
+++ b/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
@@ -0,0 +1,239 @@
+- // MIR for `variant_a::{closure#0}` before ReferencePropagation
++ // MIR for `variant_a::{closure#0}` after ReferencePropagation
+  
+  fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
+      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
+      let _3: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+      let _4: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+      let _5: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+      let _6: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
+      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
+      let mut _9: &&usize;                 // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
+      let mut _10: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+      let _11: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+      let mut _12: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
+      let mut _13: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
+      let mut _14: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+      let _15: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+      let mut _16: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
+      let mut _17: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
+      let mut _18: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
+      let mut _19: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+      let _20: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+      let mut _21: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
+      let mut _22: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
+      let mut _23: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+      let _24: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+      let mut _25: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _26: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+      let mut _31: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      let mut _32: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      let mut _37: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      let mut _38: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      let mut _43: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      let mut _44: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      let mut _49: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      let mut _50: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
+      scope 1 {
+          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+          scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
+              debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _29: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _30: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _33: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _34: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              }
+          }
+          scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
+              debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _35: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _36: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => _35;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => _36;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _39: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _40: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              }
+          }
+          scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
+              debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _41: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _42: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => _41;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => _42;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _45: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _46: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              }
+          }
+          scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
+              debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _47: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              let mut _48: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug self => _47;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  debug other => _48;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _51: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                  let mut _52: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+              }
+          }
+      }
+  
+      bb0: {
+          _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+          _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+          _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+          _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+          _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+          _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+          _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+          _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
+          StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+          _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+          StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+          _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+          _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+-         _29 = deref_copy (*_9);          // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _30 = deref_copy (*_10);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _29 = deref_copy _3;             // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _30 = deref_copy _11;            // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _33 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _34 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _8 = Le(move _33, move _34);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+          StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+          StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+      }
+  
+      bb1: {
+          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+      }
+  
+      bb2: {
+          StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+          StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
+          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+          _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+          StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+          StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+          _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+          _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+-         _35 = deref_copy (*_18);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _36 = deref_copy (*_19);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _35 = deref_copy _5;             // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _36 = deref_copy _20;            // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _39 = (*_35);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _40 = (*_36);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _17 = Le(move _39, move _40);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+          StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+          switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+      }
+  
+      bb3: {
+          StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
+      }
+  
+      bb4: {
+          _7 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+          StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+      }
+  
+      bb5: {
+          StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
+          StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+          _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+-         _41 = deref_copy (*_13);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _42 = deref_copy (*_14);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _41 = deref_copy _6;             // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _42 = deref_copy _15;            // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _45 = (*_41);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _46 = (*_42);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _12 = Le(move _45, move _46);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+          StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+          switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+      }
+  
+      bb6: {
+          _16 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+      }
+  
+      bb7: {
+          StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
+          StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+          _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+          StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+-         _47 = deref_copy (*_22);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+-         _48 = deref_copy (*_23);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _47 = deref_copy _4;             // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
++         _48 = deref_copy _24;            // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _51 = (*_47);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageLive(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _52 = (*_48);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          _21 = Le(move _51, move _52);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+          StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+      }
+  
+      bb8: {
+          StorageDead(_21);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          StorageDead(_17);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+          _0 = move _16;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+      }
+  }
+  
diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff
new file mode 100644
index 00000000000..d1241c6b024
--- /dev/null
+++ b/tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff
@@ -0,0 +1,103 @@
+- // MIR for `variant_b::{closure#0}` before ReferencePropagation
++ // MIR for `variant_b::{closure#0}` after ReferencePropagation
+  
+  fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:12:25: 12:41], _2: &&(usize, usize, usize, usize)) -> bool {
+      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:42: +0:42
+      let _3: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+      let _4: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+      let _5: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+      let _6: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:58
+      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:48
+      let mut _9: usize;                   // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:43
+      let mut _10: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:47: +0:48
+      let mut _11: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:58
+      let mut _12: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:53
+      let mut _13: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:57: +0:58
+      let mut _14: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:78
+      let mut _15: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:68
+      let mut _16: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:63
+      let mut _17: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:67: +0:68
+      let mut _18: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:78
+      let mut _19: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:73
+      let mut _20: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
+      let mut _21: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+      let mut _22: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+      let mut _23: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+      let mut _24: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+      scope 1 {
+          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:29: +0:30
+          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:32: +0:33
+          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:35: +0:36
+          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:38: +0:39
+      }
+  
+      bb0: {
+          _21 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+          _3 = ((*_21).0: usize);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+          _22 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+          _4 = ((*_22).1: usize);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+          _23 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+          _5 = ((*_23).2: usize);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+          _24 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+          _6 = ((*_24).3: usize);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+          _8 = Le(_3, _5);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+      }
+  
+      bb1: {
+          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+      }
+  
+      bb2: {
+          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+          _15 = Le(_5, _3);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+          switchInt(move _15) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+      }
+  
+      bb3: {
+          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+          return;                          // scope 0 at $DIR/slice_filter.rs:+0:78: +0:78
+      }
+  
+      bb4: {
+          _7 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+      }
+  
+      bb5: {
+          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+          _11 = Le(_6, _4);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+          _7 = move _11;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+          switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+      }
+  
+      bb6: {
+          _14 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+      }
+  
+      bb7: {
+          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+          _18 = Le(_4, _6);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+          _14 = move _18;                  // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+      }
+  
+      bb8: {
+          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+          _0 = move _14;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+      }
+  }
+