about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs41
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs18
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs3
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs3
-rw-r--r--compiler/rustc_mir_transform/src/ssa.rs55
-rw-r--r--tests/coverage/issue-83601.cov-map6
-rw-r--r--tests/coverage/issue-84561.cov-map22
-rw-r--r--tests/crashes/111883.rs40
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff24
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff24
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff (renamed from tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-abort.diff)6
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff (renamed from tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff)6
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff23
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff23
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.rs71
-rw-r--r--tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff29
-rw-r--r--tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff29
-rw-r--r--tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff18
-rw-r--r--tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff18
-rw-r--r--tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff27
-rw-r--r--tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff27
-rw-r--r--tests/mir-opt/gvn.rs65
-rw-r--r--tests/mir-opt/gvn.slices.GVN.panic-abort.diff38
-rw-r--r--tests/mir-opt/gvn.slices.GVN.panic-unwind.diff38
-rw-r--r--tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff3
-rw-r--r--tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff3
-rw-r--r--tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir211
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff6
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff6
-rw-r--r--tests/mir-opt/reference_prop.rs10
30 files changed, 591 insertions, 302 deletions
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 0119b95cced..c1f9313a377 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -3,7 +3,6 @@ use rustc_index::IndexSlice;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
-use rustc_mir_dataflow::impls::borrowed_locals;
 
 use crate::ssa::SsaLocals;
 
@@ -32,8 +31,8 @@ impl<'tcx> MirPass<'tcx> for CopyProp {
 }
 
 fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let borrowed_locals = borrowed_locals(body);
-    let ssa = SsaLocals::new(body);
+    let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+    let ssa = SsaLocals::new(tcx, body, param_env);
 
     let fully_moved = fully_moved_locals(&ssa, body);
     debug!(?fully_moved);
@@ -51,7 +50,7 @@ fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         tcx,
         copy_classes: ssa.copy_classes(),
         fully_moved,
-        borrowed_locals,
+        borrowed_locals: ssa.borrowed_locals(),
         storage_to_remove,
     }
     .visit_body_preserves_cfg(body);
@@ -101,7 +100,7 @@ struct Replacer<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     fully_moved: BitSet<Local>,
     storage_to_remove: BitSet<Local>,
-    borrowed_locals: BitSet<Local>,
+    borrowed_locals: &'a BitSet<Local>,
     copy_classes: &'a IndexSlice<Local, Local>,
 }
 
@@ -112,6 +111,12 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
 
     fn visit_local(&mut self, local: &mut Local, ctxt: PlaceContext, _: Location) {
         let new_local = self.copy_classes[*local];
+        // We must not unify two locals that are borrowed. But this is fine if one is borrowed and
+        // the other is not. We chose to check the original local, and not the target. That way, if
+        // the original local is borrowed and the target is not, we do not pessimize the whole class.
+        if self.borrowed_locals.contains(*local) {
+            return;
+        }
         match ctxt {
             // Do not modify the local in storage statements.
             PlaceContext::NonUse(NonUseContext::StorageLive | NonUseContext::StorageDead) => {}
@@ -122,32 +127,14 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
         }
     }
 
-    fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext, loc: Location) {
+    fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, loc: Location) {
         if let Some(new_projection) = self.process_projection(place.projection, loc) {
             place.projection = self.tcx().mk_place_elems(&new_projection);
         }
 
-        let observes_address = match ctxt {
-            PlaceContext::NonMutatingUse(
-                NonMutatingUseContext::SharedBorrow
-                | NonMutatingUseContext::FakeBorrow
-                | NonMutatingUseContext::AddressOf,
-            ) => true,
-            // For debuginfo, merging locals is ok.
-            PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
-                self.borrowed_locals.contains(place.local)
-            }
-            _ => false,
-        };
-        if observes_address && !place.is_indirect() {
-            // We observe the address of `place.local`. Do not replace it.
-        } else {
-            self.visit_local(
-                &mut place.local,
-                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
-                loc,
-            )
-        }
+        // Any non-mutating use context is ok.
+        let ctxt = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
+        self.visit_local(&mut place.local, ctxt, loc)
     }
 
     fn visit_operand(&mut self, operand: &mut Operand<'tcx>, loc: Location) {
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 24832086b16..4dd595ce1e1 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -121,7 +121,7 @@ impl<'tcx> MirPass<'tcx> for GVN {
 
 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 ssa = SsaLocals::new(body);
+    let ssa = SsaLocals::new(tcx, body, param_env);
     // Clone dominators as we need them while mutating the body.
     let dominators = body.basic_blocks.dominators().clone();
 
@@ -724,6 +724,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
         // Invariant: `value` holds the value up-to the `index`th projection excluded.
         let mut value = self.locals[place.local]?;
         for (index, proj) in place.projection.iter().enumerate() {
+            if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
+                && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
+                && let AddressKind::Ref(BorrowKind::Shared) = kind
+                && let Some(v) = self.simplify_place_value(&mut pointee, location)
+            {
+                value = v;
+                place_ref = pointee.project_deeper(&place.projection[index..], self.tcx).as_ref();
+            }
             if let Some(local) = self.try_as_local(value, location) {
                 // Both `local` and `Place { local: place.local, projection: projection[..index] }`
                 // hold the same value. Therefore, following place holds the value in the original
@@ -735,6 +743,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
             value = self.project(base, value, proj)?;
         }
 
+        if let Value::Projection(pointer, ProjectionElem::Deref) = *self.get(value)
+            && let Value::Address { place: mut pointee, kind, .. } = *self.get(pointer)
+            && let AddressKind::Ref(BorrowKind::Shared) = kind
+            && let Some(v) = self.simplify_place_value(&mut pointee, location)
+        {
+            value = v;
+            place_ref = pointee.project_deeper(&[], self.tcx).as_ref();
+        }
         if let Some(new_local) = self.try_as_local(value, location) {
             place_ref = PlaceRef { local: new_local, projection: &[] };
         }
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index 128634bd7f2..c26a5461633 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -22,7 +22,8 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
 }
 
 fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
-    let ssa = SsaLocals::new(body);
+    let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+    let ssa = SsaLocals::new(tcx, body, param_env);
 
     let slice_lengths = compute_slice_length(tcx, &ssa, body);
     debug!(?slice_lengths);
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index d5642be5513..044ae32c1d4 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -82,7 +82,8 @@ impl<'tcx> MirPass<'tcx> for ReferencePropagation {
 }
 
 fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
-    let ssa = SsaLocals::new(body);
+    let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
+    let ssa = SsaLocals::new(tcx, body, param_env);
 
     let mut replacer = compute_replacement(tcx, body, &ssa);
     debug!(?replacer.targets);
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index fddc62e6652..55fed7d9da2 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -2,8 +2,9 @@
 //! 1/ They are only assigned-to once, either as a function parameter, or in an assign statement;
 //! 2/ This single assignment dominates all uses;
 //!
-//! As a consequence of rule 2, we consider that borrowed locals are not SSA, even if they are
-//! `Freeze`, as we do not track that the assignment dominates all uses of the borrow.
+//! As we do not track indirect assignments, a local that has its address taken (either by
+//! AddressOf or by borrowing) is considered non-SSA. However, it is UB to modify through an
+//! immutable borrow of a `Freeze` local. Those can still be considered to be SSA.
 
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::BitSet;
@@ -11,6 +12,7 @@ use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::middle::resolve_bound_vars::Set1;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
+use rustc_middle::ty::{ParamEnv, TyCtxt};
 
 pub struct SsaLocals {
     /// Assignments to each local. This defines whether the local is SSA.
@@ -24,6 +26,8 @@ pub struct SsaLocals {
     /// 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 SSA locals that are immutably borrowed.
+    borrowed_locals: BitSet<Local>,
 }
 
 pub enum AssignedValue<'a, 'tcx> {
@@ -33,15 +37,22 @@ pub enum AssignedValue<'a, 'tcx> {
 }
 
 impl SsaLocals {
-    pub fn new<'tcx>(body: &Body<'tcx>) -> SsaLocals {
+    pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals {
         let assignment_order = Vec::with_capacity(body.local_decls.len());
 
         let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
         let dominators = body.basic_blocks.dominators();
 
         let direct_uses = IndexVec::from_elem(0, &body.local_decls);
-        let mut visitor =
-            SsaVisitor { body, assignments, assignment_order, dominators, direct_uses };
+        let borrowed_locals = BitSet::new_empty(body.local_decls.len());
+        let mut visitor = SsaVisitor {
+            body,
+            assignments,
+            assignment_order,
+            dominators,
+            direct_uses,
+            borrowed_locals,
+        };
 
         for local in body.args_iter() {
             visitor.assignments[local] = Set1::One(DefLocation::Argument);
@@ -58,6 +69,16 @@ impl SsaLocals {
             visitor.visit_var_debug_info(var_debug_info);
         }
 
+        // The immutability of shared borrows only works on `Freeze` locals. If the visitor found
+        // borrows, we need to check the types. For raw pointers and mutable borrows, the locals
+        // have already been marked as non-SSA.
+        debug!(?visitor.borrowed_locals);
+        for local in visitor.borrowed_locals.iter() {
+            if !body.local_decls[local].ty.is_freeze(tcx, param_env) {
+                visitor.assignments[local] = Set1::Many;
+            }
+        }
+
         debug!(?visitor.assignments);
         debug!(?visitor.direct_uses);
 
@@ -70,6 +91,7 @@ impl SsaLocals {
             assignments: visitor.assignments,
             assignment_order: visitor.assignment_order,
             direct_uses: visitor.direct_uses,
+            borrowed_locals: visitor.borrowed_locals,
             // This is filled by `compute_copy_classes`.
             copy_classes: IndexVec::default(),
         };
@@ -174,6 +196,11 @@ impl SsaLocals {
         &self.copy_classes
     }
 
+    /// Set of SSA locals that are immutably borrowed.
+    pub fn borrowed_locals(&self) -> &BitSet<Local> {
+        &self.borrowed_locals
+    }
+
     /// Make a property uniform on a copy equivalence class by removing elements.
     pub fn meet_copy_equivalence(&self, property: &mut BitSet<Local>) {
         // Consolidate to have a local iff all its copies are.
@@ -208,6 +235,8 @@ struct SsaVisitor<'tcx, 'a> {
     assignments: IndexVec<Local, Set1<DefLocation>>,
     assignment_order: Vec<Local>,
     direct_uses: IndexVec<Local, u32>,
+    // Track locals that are immutably borrowed, so we can check their type is `Freeze` later.
+    borrowed_locals: BitSet<Local>,
 }
 
 impl SsaVisitor<'_, '_> {
@@ -232,16 +261,18 @@ impl<'tcx> Visitor<'tcx> for SsaVisitor<'tcx, '_> {
             PlaceContext::MutatingUse(MutatingUseContext::Projection)
             | PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => bug!(),
             // Anything can happen with raw pointers, so remove them.
-            // We do not verify that all uses of the borrow dominate the assignment to `local`,
-            // so we have to remove them too.
-            PlaceContext::NonMutatingUse(
-                NonMutatingUseContext::SharedBorrow
-                | NonMutatingUseContext::FakeBorrow
-                | NonMutatingUseContext::AddressOf,
-            )
+            PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf)
             | PlaceContext::MutatingUse(_) => {
                 self.assignments[local] = Set1::Many;
             }
+            // Immutable borrows are ok, but we need to delay a check that the type is `Freeze`.
+            PlaceContext::NonMutatingUse(
+                NonMutatingUseContext::SharedBorrow | NonMutatingUseContext::FakeBorrow,
+            ) => {
+                self.borrowed_locals.insert(local);
+                self.check_dominates(local, loc);
+                self.direct_uses[local] += 1;
+            }
             PlaceContext::NonMutatingUse(_) => {
                 self.check_dominates(local, loc);
                 self.direct_uses[local] += 1;
diff --git a/tests/coverage/issue-83601.cov-map b/tests/coverage/issue-83601.cov-map
index f2447e3c92c..ddb4407881a 100644
--- a/tests/coverage/issue-83601.cov-map
+++ b/tests/coverage/issue-83601.cov-map
@@ -1,12 +1,12 @@
 Function name: issue_83601::main
-Raw bytes (21): 0x[01, 01, 01, 05, 09, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
+Raw bytes (21): 0x[01, 01, 01, 05, 00, 03, 01, 06, 01, 02, 1c, 05, 03, 09, 01, 1c, 02, 02, 05, 03, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 1
-- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 0 operands: lhs = Counter(1), rhs = Zero
 Number of file 0 mappings: 3
 - Code(Counter(0)) at (prev + 6, 1) to (start + 2, 28)
 - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 28)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 3, 2)
-    = (c1 - c2)
+    = (c1 - Zero)
 
diff --git a/tests/coverage/issue-84561.cov-map b/tests/coverage/issue-84561.cov-map
index a81884ea942..ab66a2fffce 100644
--- a/tests/coverage/issue-84561.cov-map
+++ b/tests/coverage/issue-84561.cov-map
@@ -77,22 +77,22 @@ Number of file 0 mappings: 1
 - Code(Counter(0)) at (prev + 167, 9) to (start + 2, 10)
 
 Function name: issue_84561::test3
-Raw bytes (436): 0x[01, 01, 41, 05, 09, 0d, 00, 15, 19, 12, 00, 15, 19, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 41, 2e, 45, 3d, 41, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 00, fe, 01, 82, 02, 00, 69, 6d, 69, 6d, 82, 02, 00, 69, 6d, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
+Raw bytes (436): 0x[01, 01, 41, 05, 00, 0d, 00, 15, 00, 12, 00, 15, 00, 21, 00, 1e, 00, 21, 00, 31, 00, 3d, 00, 2e, 45, 3d, 00, 42, 49, 45, 00, 3f, 51, 42, 49, 45, 00, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 92, 01, 55, 51, 00, 8f, 01, 5d, 92, 01, 55, 51, 00, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 82, 01, 65, 87, 01, 61, 5d, 8a, 01, 8f, 01, 5d, 92, 01, 55, 51, 00, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 00, fe, 01, 82, 02, 00, 69, 6d, 69, 6d, 82, 02, 00, 69, 6d, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, ee, 01, 00, f3, 01, 7d, 75, f6, 01, fb, 01, 79, 00, fe, 01, 82, 02, 00, 69, 6d, 33, 01, 08, 01, 03, 1c, 05, 04, 09, 01, 1c, 02, 02, 05, 04, 1f, 0d, 05, 05, 00, 1f, 06, 01, 05, 00, 1f, 15, 01, 09, 01, 1c, 12, 02, 05, 00, 1f, 0e, 01, 05, 00, 0f, 00, 00, 20, 00, 30, 21, 01, 05, 03, 0f, 00, 03, 20, 00, 30, 00, 00, 33, 00, 41, 00, 00, 4b, 00, 5a, 1e, 01, 05, 00, 0f, 00, 05, 09, 03, 10, 00, 05, 0d, 00, 1b, 00, 02, 0d, 00, 1c, 1a, 04, 09, 05, 06, 31, 06, 05, 03, 06, 22, 04, 05, 03, 06, 3d, 04, 09, 04, 06, 2e, 05, 08, 00, 0f, 45, 01, 09, 03, 0a, 2a, 05, 09, 03, 0a, 3f, 05, 08, 00, 0f, 51, 01, 09, 00, 13, 00, 03, 0d, 00, 1d, 3a, 03, 09, 00, 13, 00, 03, 0d, 00, 1d, 87, 01, 03, 05, 00, 0f, 8f, 01, 01, 0c, 00, 13, 5d, 01, 0d, 00, 13, 8a, 01, 02, 0d, 00, 13, 82, 01, 04, 05, 02, 13, 65, 03, 0d, 00, 13, 7e, 02, 0d, 00, 13, f3, 01, 03, 05, 00, 0f, 69, 01, 0c, 00, 13, 6d, 01, 0d, 03, 0e, 75, 04, 0d, 00, 13, fb, 01, 02, 0d, 00, 17, 82, 02, 01, 14, 00, 1b, 00, 01, 15, 00, 1b, fe, 01, 02, 15, 00, 1b, f6, 01, 04, 0d, 00, 13, 7d, 03, 09, 00, 19, ee, 01, 02, 05, 00, 0f, ea, 01, 03, 09, 00, 22, 00, 02, 05, 00, 0f, 00, 03, 09, 00, 2c, 00, 02, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 65
-- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 0 operands: lhs = Counter(1), rhs = Zero
 - expression 1 operands: lhs = Counter(3), rhs = Zero
-- expression 2 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 2 operands: lhs = Counter(5), rhs = Zero
 - expression 3 operands: lhs = Expression(4, Sub), rhs = Zero
-- expression 4 operands: lhs = Counter(5), rhs = Counter(6)
+- expression 4 operands: lhs = Counter(5), rhs = Zero
 - expression 5 operands: lhs = Counter(8), rhs = Zero
 - expression 6 operands: lhs = Expression(7, Sub), rhs = Zero
 - expression 7 operands: lhs = Counter(8), rhs = Zero
 - expression 8 operands: lhs = Counter(12), rhs = Zero
-- expression 9 operands: lhs = Counter(15), rhs = Counter(16)
+- expression 9 operands: lhs = Counter(15), rhs = Zero
 - expression 10 operands: lhs = Expression(11, Sub), rhs = Counter(17)
-- expression 11 operands: lhs = Counter(15), rhs = Counter(16)
+- expression 11 operands: lhs = Counter(15), rhs = Zero
 - expression 12 operands: lhs = Expression(16, Sub), rhs = Counter(18)
 - expression 13 operands: lhs = Counter(17), rhs = Zero
 - expression 14 operands: lhs = Expression(15, Add), rhs = Counter(20)
@@ -150,15 +150,15 @@ Number of file 0 mappings: 51
 - Code(Counter(0)) at (prev + 8, 1) to (start + 3, 28)
 - Code(Counter(1)) at (prev + 4, 9) to (start + 1, 28)
 - Code(Expression(0, Sub)) at (prev + 2, 5) to (start + 4, 31)
-    = (c1 - c2)
+    = (c1 - Zero)
 - Code(Counter(3)) at (prev + 5, 5) to (start + 0, 31)
 - Code(Expression(1, Sub)) at (prev + 1, 5) to (start + 0, 31)
     = (c3 - Zero)
 - Code(Counter(5)) at (prev + 1, 9) to (start + 1, 28)
 - Code(Expression(4, Sub)) at (prev + 2, 5) to (start + 0, 31)
-    = (c5 - c6)
+    = (c5 - Zero)
 - Code(Expression(3, Sub)) at (prev + 1, 5) to (start + 0, 15)
-    = ((c5 - c6) - Zero)
+    = ((c5 - Zero) - Zero)
 - Code(Zero) at (prev + 0, 32) to (start + 0, 48)
 - Code(Counter(8)) at (prev + 1, 5) to (start + 3, 15)
 - Code(Zero) at (prev + 3, 32) to (start + 0, 48)
@@ -176,10 +176,10 @@ Number of file 0 mappings: 51
     = (c12 - Zero)
 - Code(Counter(15)) at (prev + 4, 9) to (start + 4, 6)
 - Code(Expression(11, Sub)) at (prev + 5, 8) to (start + 0, 15)
-    = (c15 - c16)
+    = (c15 - Zero)
 - Code(Counter(17)) at (prev + 1, 9) to (start + 3, 10)
 - Code(Expression(10, Sub)) at (prev + 5, 9) to (start + 3, 10)
-    = ((c15 - c16) - c17)
+    = ((c15 - Zero) - c17)
 - Code(Expression(15, Add)) at (prev + 5, 8) to (start + 0, 15)
     = ((c17 - Zero) + c18)
 - Code(Counter(20)) at (prev + 1, 9) to (start + 0, 19)
diff --git a/tests/crashes/111883.rs b/tests/crashes/111883.rs
deleted file mode 100644
index fa72b28c228..00000000000
--- a/tests/crashes/111883.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-//@ known-bug: #111883
-#![crate_type = "lib"]
-#![feature(arbitrary_self_types, no_core, lang_items)]
-#![no_core]
-
-#[lang = "sized"]
-trait Sized {}
-#[lang = "copy"]
-trait Copy {}
-#[lang = "receiver"]
-trait Receiver {}
-#[lang = "dispatch_from_dyn"]
-trait DispatchFromDyn<T> {}
-impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
-#[lang = "unsize"]
-trait Unsize<T: ?Sized> {}
-#[lang = "coerce_unsized"]
-pub trait CoerceUnsized<T: ?Sized> {}
-impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
-
-#[lang = "drop_in_place"]
-fn drop_in_place_fn<T>(a: &dyn Trait2<T>) {}
-
-pub trait Trait1 {
-    fn foo(&self);
-}
-
-pub struct Type1;
-
-impl Trait1 for Type1 {
-    fn foo(&self) {}
-}
-
-pub trait Trait2<T> {}
-
-pub fn bar1() {
-    let a = Type1;
-    let b = &a as &dyn Trait1;
-    b.foo();
-}
diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff
new file mode 100644
index 00000000000..897592a0e2f
--- /dev/null
+++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-abort.diff
@@ -0,0 +1,24 @@
+- // MIR for `borrowed` before CopyProp
++ // MIR for `borrowed` after CopyProp
+  
+  fn borrowed(_1: T) -> bool {
+      let mut _0: bool;
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+-         _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+-         _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
++         _0 = opaque::<T>(_1) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff
new file mode 100644
index 00000000000..33c05af91a1
--- /dev/null
+++ b/tests/mir-opt/copy-prop/borrowed_local.borrowed.CopyProp.panic-unwind.diff
@@ -0,0 +1,24 @@
+- // MIR for `borrowed` before CopyProp
++ // MIR for `borrowed` after CopyProp
+  
+  fn borrowed(_1: T) -> bool {
+      let mut _0: bool;
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+-         _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+-         _0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
++         _0 = opaque::<T>(_1) -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff
index 46534076c29..3d6b5dffba4 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-abort.diff
+++ b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-abort.diff
@@ -1,7 +1,7 @@
-- // MIR for `f` before CopyProp
-+ // MIR for `f` after CopyProp
+- // MIR for `compare_address` before CopyProp
++ // MIR for `compare_address` after CopyProp
   
-  fn f() -> bool {
+  fn compare_address() -> bool {
       let mut _0: bool;
       let mut _1: u8;
       let mut _2: &u8;
diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff
index b702e3b7d1e..0f29d2681de 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.panic-unwind.diff
+++ b/tests/mir-opt/copy-prop/borrowed_local.compare_address.CopyProp.panic-unwind.diff
@@ -1,7 +1,7 @@
-- // MIR for `f` before CopyProp
-+ // MIR for `f` after CopyProp
+- // MIR for `compare_address` before CopyProp
++ // MIR for `compare_address` after CopyProp
   
-  fn f() -> bool {
+  fn compare_address() -> bool {
       let mut _0: bool;
       let mut _1: u8;
       let mut _2: &u8;
diff --git a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff
new file mode 100644
index 00000000000..af2aeb0dcab
--- /dev/null
+++ b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-abort.diff
@@ -0,0 +1,23 @@
+- // MIR for `non_freeze` before CopyProp
++ // MIR for `non_freeze` after CopyProp
+  
+  fn non_freeze(_1: T) -> bool {
+      let mut _0: bool;
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+          _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff
new file mode 100644
index 00000000000..040ed0aec16
--- /dev/null
+++ b/tests/mir-opt/copy-prop/borrowed_local.non_freeze.CopyProp.panic-unwind.diff
@@ -0,0 +1,23 @@
+- // MIR for `non_freeze` before CopyProp
++ // MIR for `non_freeze` after CopyProp
+  
+  fn non_freeze(_1: T) -> bool {
+      let mut _0: bool;
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+          _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          _0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs
index 74ac6281a89..512287dd176 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.rs
+++ b/tests/mir-opt/copy-prop/borrowed_local.rs
@@ -1,10 +1,10 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 //@ test-mir-pass: CopyProp
 
-#![feature(custom_mir, core_intrinsics)]
+#![feature(custom_mir, core_intrinsics, freeze)]
 #![allow(unused_assignments)]
 extern crate core;
+use core::marker::Freeze;
 use core::intrinsics::mir::*;
 
 fn opaque(_: impl Sized) -> bool { true }
@@ -14,7 +14,16 @@ fn cmp_ref(a: &u8, b: &u8) -> bool {
 }
 
 #[custom_mir(dialect = "analysis", phase = "post-cleanup")]
-fn f() -> bool {
+fn compare_address() -> bool {
+    // CHECK-LABEL: fn compare_address(
+    // CHECK: bb0: {
+    // CHECK-NEXT: _1 = const 5_u8;
+    // CHECK-NEXT: _2 = &_1;
+    // CHECK-NEXT: _3 = _1;
+    // CHECK-NEXT: _4 = &_3;
+    // CHECK-NEXT: _0 = cmp_ref(_2, _4)
+    // CHECK: bb1: {
+    // CHECK-NEXT: _0 = opaque::<u8>(_3)
     mir!(
         {
             let a = 5_u8;
@@ -34,8 +43,60 @@ fn f() -> bool {
     )
 }
 
+/// Generic type `T` is `Freeze`, so shared borrows are immutable.
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn borrowed<T: Copy + Freeze>(x: T) -> bool {
+    // CHECK-LABEL: fn borrowed(
+    // CHECK: bb0: {
+    // CHECK-NEXT: _3 = &_1;
+    // CHECK-NEXT: _0 = opaque::<&T>(_3)
+    // CHECK: bb1: {
+    // CHECK-NEXT: _0 = opaque::<T>(_1)
+    mir!(
+        {
+            let a = x;
+            let r1 = &x;
+            Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
+        }
+        next = {
+            Call(RET = opaque(a), ReturnTo(ret), UnwindContinue())
+        }
+        ret = {
+            Return()
+        }
+    )
+}
+
+/// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable.
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn non_freeze<T: Copy>(x: T) -> bool {
+    // CHECK-LABEL: fn non_freeze(
+    // CHECK: bb0: {
+    // CHECK-NEXT: _2 = _1;
+    // CHECK-NEXT: _3 = &_1;
+    // CHECK-NEXT: _0 = opaque::<&T>(_3)
+    // CHECK: bb1: {
+    // CHECK-NEXT: _0 = opaque::<T>(_2)
+    mir!(
+        {
+            let a = x;
+            let r1 = &x;
+            Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
+        }
+        next = {
+            Call(RET = opaque(a), ReturnTo(ret), UnwindContinue())
+        }
+        ret = {
+            Return()
+        }
+    )
+}
+
 fn main() {
-    assert!(!f());
+    assert!(!compare_address());
+    non_freeze(5);
 }
 
-// EMIT_MIR borrowed_local.f.CopyProp.diff
+// EMIT_MIR borrowed_local.compare_address.CopyProp.diff
+// EMIT_MIR borrowed_local.borrowed.CopyProp.diff
+// EMIT_MIR borrowed_local.non_freeze.CopyProp.diff
diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff
new file mode 100644
index 00000000000..9520bd382ee
--- /dev/null
+++ b/tests/mir-opt/gvn.borrowed.GVN.panic-abort.diff
@@ -0,0 +1,29 @@
+- // MIR for `borrowed` before GVN
++ // MIR for `borrowed` after GVN
+  
+  fn borrowed(_1: T) -> () {
+      let mut _0: ();
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+          _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+-         _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
++         _0 = opaque::<T>(_1) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+-         _0 = opaque::<T>((*_3)) -> [return: bb3, unwind unreachable];
++         _0 = opaque::<T>(_1) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..4f5d76d5644
--- /dev/null
+++ b/tests/mir-opt/gvn.borrowed.GVN.panic-unwind.diff
@@ -0,0 +1,29 @@
+- // MIR for `borrowed` before GVN
++ // MIR for `borrowed` after GVN
+  
+  fn borrowed(_1: T) -> () {
+      let mut _0: ();
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+          _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+-         _0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
++         _0 = opaque::<T>(_1) -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
+-         _0 = opaque::<T>((*_3)) -> [return: bb3, unwind continue];
++         _0 = opaque::<T>(_1) -> [return: bb3, unwind continue];
+      }
+  
+      bb3: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff
index 02bf95840da..68cb4d55e7b 100644
--- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-abort.diff
@@ -8,10 +8,10 @@
       let mut _3: fn(u8) -> u8;
       let _5: ();
       let mut _6: fn(u8) -> u8;
-      let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
+      let mut _9: {closure@$DIR/gvn.rs:612:19: 612:21};
       let _10: ();
       let mut _11: fn();
-      let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
+      let mut _13: {closure@$DIR/gvn.rs:612:19: 612:21};
       let _14: ();
       let mut _15: fn();
       scope 1 {
@@ -19,7 +19,7 @@
           let _4: fn(u8) -> u8;
           scope 2 {
               debug g => _4;
-              let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
+              let _7: {closure@$DIR/gvn.rs:612:19: 612:21};
               scope 3 {
                   debug closure => _7;
                   let _8: fn();
@@ -62,16 +62,16 @@
           StorageDead(_6);
           StorageDead(_5);
 -         StorageLive(_7);
--         _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
+-         _7 = {closure@$DIR/gvn.rs:612:19: 612:21};
 -         StorageLive(_8);
 +         nop;
-+         _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
++         _7 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
 +         nop;
           StorageLive(_9);
 -         _9 = _7;
 -         _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
-+         _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
-+         _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
++         _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
++         _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
           StorageDead(_9);
           StorageLive(_10);
           StorageLive(_11);
@@ -88,8 +88,8 @@
           StorageLive(_13);
 -         _13 = _7;
 -         _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
-+         _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
-+         _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
++         _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
++         _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
           StorageDead(_13);
           StorageLive(_14);
           StorageLive(_15);
diff --git a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff
index c5dcc8a8ec9..fa184348b3b 100644
--- a/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.fn_pointers.GVN.panic-unwind.diff
@@ -8,10 +8,10 @@
       let mut _3: fn(u8) -> u8;
       let _5: ();
       let mut _6: fn(u8) -> u8;
-      let mut _9: {closure@$DIR/gvn.rs:610:19: 610:21};
+      let mut _9: {closure@$DIR/gvn.rs:612:19: 612:21};
       let _10: ();
       let mut _11: fn();
-      let mut _13: {closure@$DIR/gvn.rs:610:19: 610:21};
+      let mut _13: {closure@$DIR/gvn.rs:612:19: 612:21};
       let _14: ();
       let mut _15: fn();
       scope 1 {
@@ -19,7 +19,7 @@
           let _4: fn(u8) -> u8;
           scope 2 {
               debug g => _4;
-              let _7: {closure@$DIR/gvn.rs:610:19: 610:21};
+              let _7: {closure@$DIR/gvn.rs:612:19: 612:21};
               scope 3 {
                   debug closure => _7;
                   let _8: fn();
@@ -62,16 +62,16 @@
           StorageDead(_6);
           StorageDead(_5);
 -         StorageLive(_7);
--         _7 = {closure@$DIR/gvn.rs:610:19: 610:21};
+-         _7 = {closure@$DIR/gvn.rs:612:19: 612:21};
 -         StorageLive(_8);
 +         nop;
-+         _7 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
++         _7 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
 +         nop;
           StorageLive(_9);
 -         _9 = _7;
 -         _8 = move _9 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
-+         _9 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
-+         _8 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
++         _9 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
++         _8 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
           StorageDead(_9);
           StorageLive(_10);
           StorageLive(_11);
@@ -88,8 +88,8 @@
           StorageLive(_13);
 -         _13 = _7;
 -         _12 = move _13 as fn() (PointerCoercion(ClosureFnPointer(Normal)));
-+         _13 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21};
-+         _12 = const ZeroSized: {closure@$DIR/gvn.rs:610:19: 610:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
++         _13 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21};
++         _12 = const ZeroSized: {closure@$DIR/gvn.rs:612:19: 612:21} as fn() (PointerCoercion(ClosureFnPointer(Normal)));
           StorageDead(_13);
           StorageLive(_14);
           StorageLive(_15);
diff --git a/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff b/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff
new file mode 100644
index 00000000000..7b6ed096118
--- /dev/null
+++ b/tests/mir-opt/gvn.non_freeze.GVN.panic-abort.diff
@@ -0,0 +1,27 @@
+- // MIR for `non_freeze` before GVN
++ // MIR for `non_freeze` after GVN
+  
+  fn non_freeze(_1: T) -> () {
+      let mut _0: ();
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+          _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
+          _0 = opaque::<T>(_2) -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
+          _0 = opaque::<T>((*_3)) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff b/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff
new file mode 100644
index 00000000000..641a2f4609a
--- /dev/null
+++ b/tests/mir-opt/gvn.non_freeze.GVN.panic-unwind.diff
@@ -0,0 +1,27 @@
+- // MIR for `non_freeze` before GVN
++ // MIR for `non_freeze` after GVN
+  
+  fn non_freeze(_1: T) -> () {
+      let mut _0: ();
+      let mut _2: T;
+      let mut _3: &T;
+  
+      bb0: {
+          _2 = _1;
+          _3 = &_1;
+          _0 = opaque::<&T>(_3) -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
+          _0 = opaque::<T>(_2) -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
+          _0 = opaque::<T>((*_3)) -> [return: bb3, unwind continue];
+      }
+  
+      bb3: {
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs
index 0484710f00e..9be30515283 100644
--- a/tests/mir-opt/gvn.rs
+++ b/tests/mir-opt/gvn.rs
@@ -6,9 +6,11 @@
 #![feature(rustc_attrs)]
 #![feature(custom_mir)]
 #![feature(core_intrinsics)]
+#![feature(freeze)]
 #![allow(unconditional_panic)]
 
 use std::intrinsics::mir::*;
+use std::marker::Freeze;
 use std::mem::transmute;
 
 struct S<T>(T);
@@ -720,6 +722,65 @@ fn wide_ptr_integer() {
     opaque(a >= b);
 }
 
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn borrowed<T: Copy + Freeze>(x: T) {
+    // CHECK-LABEL: fn borrowed(
+    // CHECK: bb0: {
+    // CHECK-NEXT: _2 = _1;
+    // CHECK-NEXT: _3 = &_1;
+    // CHECK-NEXT: _0 = opaque::<&T>(_3)
+    // CHECK: bb1: {
+    // CHECK-NEXT: _0 = opaque::<T>(_1)
+    // CHECK: bb2: {
+    // CHECK-NEXT: _0 = opaque::<T>(_1)
+    mir!(
+        {
+            let a = x;
+            let r1 = &x;
+            Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
+        }
+        next = {
+            Call(RET = opaque(a), ReturnTo(deref), UnwindContinue())
+        }
+        deref = {
+            Call(RET = opaque(*r1), ReturnTo(ret), UnwindContinue())
+        }
+        ret = {
+            Return()
+        }
+    )
+}
+
+/// Generic type `T` is not known to be `Freeze`, so shared borrows may be mutable.
+#[custom_mir(dialect = "analysis", phase = "post-cleanup")]
+fn non_freeze<T: Copy>(x: T) {
+    // CHECK-LABEL: fn non_freeze(
+    // CHECK: bb0: {
+    // CHECK-NEXT: _2 = _1;
+    // CHECK-NEXT: _3 = &_1;
+    // CHECK-NEXT: _0 = opaque::<&T>(_3)
+    // CHECK: bb1: {
+    // CHECK-NEXT: _0 = opaque::<T>(_2)
+    // CHECK: bb2: {
+    // CHECK-NEXT: _0 = opaque::<T>((*_3))
+    mir!(
+        {
+            let a = x;
+            let r1 = &x;
+            Call(RET = opaque(r1), ReturnTo(next), UnwindContinue())
+        }
+        next = {
+            Call(RET = opaque(a), ReturnTo(deref), UnwindContinue())
+        }
+        deref = {
+            Call(RET = opaque(*r1), ReturnTo(ret), UnwindContinue())
+        }
+        ret = {
+            Return()
+        }
+    )
+}
+
 fn main() {
     subexpression_elimination(2, 4, 5);
     wrap_unwrap(5);
@@ -742,6 +803,8 @@ fn main() {
     constant_index_overflow(&[5, 3]);
     wide_ptr_provenance();
     wide_ptr_integer();
+    borrowed(5);
+    non_freeze(5);
 }
 
 #[inline(never)]
@@ -773,3 +836,5 @@ fn identity<T>(x: T) -> T {
 // EMIT_MIR gvn.wide_ptr_provenance.GVN.diff
 // EMIT_MIR gvn.wide_ptr_same_provenance.GVN.diff
 // EMIT_MIR gvn.wide_ptr_integer.GVN.diff
+// EMIT_MIR gvn.borrowed.GVN.diff
+// EMIT_MIR gvn.non_freeze.GVN.diff
diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff
index 2389d98b5b3..fb67e3d5994 100644
--- a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff
@@ -111,8 +111,9 @@
           StorageLive(_7);
           StorageLive(_8);
 -         StorageLive(_9);
+-         StorageLive(_10);
++         nop;
 +         nop;
-          StorageLive(_10);
           StorageLive(_11);
           _11 = &(*_1);
           _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind unreachable];
@@ -122,8 +123,9 @@
           StorageDead(_11);
           _9 = &_10;
 -         StorageLive(_12);
+-         StorageLive(_13);
++         nop;
 +         nop;
-          StorageLive(_13);
           StorageLive(_14);
 -         _14 = &(*_4);
 +         _14 = &(*_1);
@@ -148,11 +150,12 @@
           StorageLive(_17);
           StorageLive(_18);
 -         _18 = (*_15);
-+         _18 = (*_9);
++         _18 = _10;
           StorageLive(_19);
 -         _19 = (*_16);
-+         _19 = (*_12);
-          _17 = Eq(move _18, move _19);
+-         _17 = Eq(move _18, move _19);
++         _19 = _13;
++         _17 = Eq(_10, _13);
           switchInt(move _17) -> [0: bb6, otherwise: bb5];
       }
   
@@ -163,8 +166,10 @@
           StorageDead(_17);
           StorageDead(_16);
           StorageDead(_15);
-          StorageDead(_13);
-          StorageDead(_10);
+-         StorageDead(_13);
+-         StorageDead(_10);
++         nop;
++         nop;
           StorageDead(_8);
           StorageDead(_7);
 -         StorageLive(_29);
@@ -213,8 +218,9 @@
           StorageLive(_33);
           StorageLive(_34);
 -         StorageLive(_35);
+-         StorageLive(_36);
++         nop;
 +         nop;
-          StorageLive(_36);
           StorageLive(_37);
           _37 = &(*_1);
           _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind unreachable];
@@ -224,8 +230,9 @@
           StorageDead(_37);
           _35 = &_36;
 -         StorageLive(_38);
+-         StorageLive(_39);
++         nop;
 +         nop;
-          StorageLive(_39);
           StorageLive(_40);
           _40 = &(*_29);
           _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind unreachable];
@@ -249,11 +256,12 @@
           StorageLive(_43);
           StorageLive(_44);
 -         _44 = (*_41);
-+         _44 = (*_35);
++         _44 = _36;
           StorageLive(_45);
 -         _45 = (*_42);
-+         _45 = (*_38);
-          _43 = Eq(move _44, move _45);
+-         _43 = Eq(move _44, move _45);
++         _45 = _39;
++         _43 = Eq(_36, _39);
           switchInt(move _43) -> [0: bb11, otherwise: bb10];
       }
   
@@ -264,8 +272,10 @@
           StorageDead(_43);
           StorageDead(_42);
           StorageDead(_41);
-          StorageDead(_39);
-          StorageDead(_36);
+-         StorageDead(_39);
+-         StorageDead(_36);
++         nop;
++         nop;
           StorageDead(_34);
           StorageDead(_33);
           _0 = const ();
diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff
index 50715d748e7..ae3013b011e 100644
--- a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff
@@ -111,8 +111,9 @@
           StorageLive(_7);
           StorageLive(_8);
 -         StorageLive(_9);
+-         StorageLive(_10);
++         nop;
 +         nop;
-          StorageLive(_10);
           StorageLive(_11);
           _11 = &(*_1);
           _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind continue];
@@ -122,8 +123,9 @@
           StorageDead(_11);
           _9 = &_10;
 -         StorageLive(_12);
+-         StorageLive(_13);
++         nop;
 +         nop;
-          StorageLive(_13);
           StorageLive(_14);
 -         _14 = &(*_4);
 +         _14 = &(*_1);
@@ -148,11 +150,12 @@
           StorageLive(_17);
           StorageLive(_18);
 -         _18 = (*_15);
-+         _18 = (*_9);
++         _18 = _10;
           StorageLive(_19);
 -         _19 = (*_16);
-+         _19 = (*_12);
-          _17 = Eq(move _18, move _19);
+-         _17 = Eq(move _18, move _19);
++         _19 = _13;
++         _17 = Eq(_10, _13);
           switchInt(move _17) -> [0: bb6, otherwise: bb5];
       }
   
@@ -163,8 +166,10 @@
           StorageDead(_17);
           StorageDead(_16);
           StorageDead(_15);
-          StorageDead(_13);
-          StorageDead(_10);
+-         StorageDead(_13);
+-         StorageDead(_10);
++         nop;
++         nop;
           StorageDead(_8);
           StorageDead(_7);
 -         StorageLive(_29);
@@ -213,8 +218,9 @@
           StorageLive(_33);
           StorageLive(_34);
 -         StorageLive(_35);
+-         StorageLive(_36);
++         nop;
 +         nop;
-          StorageLive(_36);
           StorageLive(_37);
           _37 = &(*_1);
           _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind continue];
@@ -224,8 +230,9 @@
           StorageDead(_37);
           _35 = &_36;
 -         StorageLive(_38);
+-         StorageLive(_39);
++         nop;
 +         nop;
-          StorageLive(_39);
           StorageLive(_40);
           _40 = &(*_29);
           _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind continue];
@@ -249,11 +256,12 @@
           StorageLive(_43);
           StorageLive(_44);
 -         _44 = (*_41);
-+         _44 = (*_35);
++         _44 = _36;
           StorageLive(_45);
 -         _45 = (*_42);
-+         _45 = (*_38);
-          _43 = Eq(move _44, move _45);
+-         _43 = Eq(move _44, move _45);
++         _45 = _39;
++         _43 = Eq(_36, _39);
           switchInt(move _43) -> [0: bb11, otherwise: bb10];
       }
   
@@ -264,8 +272,10 @@
           StorageDead(_43);
           StorageDead(_42);
           StorageDead(_41);
-          StorageDead(_39);
-          StorageDead(_36);
+-         StorageDead(_39);
+-         StorageDead(_36);
++         nop;
++         nop;
           StorageDead(_34);
           StorageDead(_33);
           _0 = const ();
diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
index c5ee0d9c44d..626367766d7 100644
--- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
@@ -17,7 +17,8 @@
           StorageLive(_3);
           _5 = const f::promoted[0];
           _3 = &(*_5);
-          _2 = ((*_3).1: E);
+-         _2 = ((*_3).1: E);
++         _2 = ((*_5).1: E);
           StorageLive(_1);
 -         _1 = ((_2 as A).1: u32);
 +         _1 = const 0_u32;
diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
index c5ee0d9c44d..626367766d7 100644
--- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
@@ -17,7 +17,8 @@
           StorageLive(_3);
           _5 = const f::promoted[0];
           _3 = &(*_5);
-          _2 = ((*_3).1: E);
+-         _2 = ((*_3).1: E);
++         _2 = ((*_5).1: E);
           StorageLive(_1);
 -         _1 = ((_2 as A).1: u32);
 +         _1 = const 0_u32;
diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
index 65cac0a81ef..dfa13230254 100644
--- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
@@ -10,18 +10,18 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
     let mut _8: &&usize;
     let _9: &usize;
     let mut _10: &&usize;
-    let mut _15: bool;
+    let mut _13: bool;
+    let mut _14: &&usize;
+    let _15: &usize;
     let mut _16: &&usize;
-    let _17: &usize;
-    let mut _18: &&usize;
+    let mut _19: bool;
+    let mut _20: &&usize;
+    let _21: &usize;
+    let mut _22: &&usize;
     let mut _23: bool;
     let mut _24: &&usize;
     let _25: &usize;
     let mut _26: &&usize;
-    let mut _31: bool;
-    let mut _32: &&usize;
-    let _33: &usize;
-    let mut _34: &&usize;
     scope 1 {
         debug a => _4;
         debug b => _5;
@@ -30,208 +30,145 @@ fn variant_a::{closure#0}(_1: &mut {closure@$DIR/slice_filter.rs:7:25: 7:39}, _2
         scope 2 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
             debug self => _8;
             debug other => _10;
-            let mut _11: &usize;
-            let mut _12: &usize;
             scope 3 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => _11;
-                debug other => _12;
-                let mut _13: usize;
-                let mut _14: usize;
+                debug self => _4;
+                debug other => _9;
+                let mut _11: usize;
+                let mut _12: usize;
             }
         }
         scope 4 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => _16;
-            debug other => _18;
-            let mut _19: &usize;
-            let mut _20: &usize;
+            debug self => _14;
+            debug other => _16;
             scope 5 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => _19;
-                debug other => _20;
-                let mut _21: usize;
-                let mut _22: usize;
+                debug self => _7;
+                debug other => _15;
+                let mut _17: usize;
+                let mut _18: usize;
             }
         }
         scope 6 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => _24;
-            debug other => _26;
-            let mut _27: &usize;
-            let mut _28: &usize;
+            debug self => _20;
+            debug other => _22;
             scope 7 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => _27;
-                debug other => _28;
-                let mut _29: usize;
-                let mut _30: usize;
+                debug self => _6;
+                debug other => _21;
             }
         }
         scope 8 (inlined std::cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => _32;
-            debug other => _34;
-            let mut _35: &usize;
-            let mut _36: &usize;
+            debug self => _24;
+            debug other => _26;
             scope 9 (inlined std::cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => _35;
-                debug other => _36;
-                let mut _37: usize;
-                let mut _38: usize;
+                debug self => _5;
+                debug other => _25;
+                let mut _27: usize;
+                let mut _28: usize;
             }
         }
     }
 
     bb0: {
-        StorageLive(_4);
         _3 = (*_2);
         _4 = &((*_3).0: usize);
-        StorageLive(_5);
         _5 = &((*_3).1: usize);
-        StorageLive(_6);
         _6 = &((*_3).2: usize);
-        StorageLive(_7);
         _7 = &((*_3).3: usize);
-        StorageLive(_15);
+        StorageLive(_13);
         StorageLive(_8);
         _8 = &_4;
         StorageLive(_10);
-        StorageLive(_9);
-        _9 = _6;
+        _9 = &((*_3).2: usize);
         _10 = &_9;
-        StorageLive(_11);
-        StorageLive(_12);
-        _11 = _4;
-        _12 = _9;
-        StorageLive(_13);
-        _13 = (*_11);
-        StorageLive(_14);
-        _14 = (*_12);
-        _15 = Le(move _13, move _14);
-        StorageDead(_14);
-        StorageDead(_13);
-        StorageDead(_12);
-        StorageDead(_11);
-        switchInt(move _15) -> [0: bb1, otherwise: bb2];
+        _11 = ((*_3).0: usize);
+        _12 = ((*_3).2: usize);
+        _13 = Le(_11, _12);
+        switchInt(move _13) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageDead(_9);
         StorageDead(_10);
         StorageDead(_8);
         goto -> bb4;
     }
 
     bb2: {
-        StorageDead(_9);
         StorageDead(_10);
         StorageDead(_8);
-        StorageLive(_23);
+        StorageLive(_19);
+        StorageLive(_14);
+        _14 = &_7;
         StorageLive(_16);
-        _16 = &_7;
-        StorageLive(_18);
+        _15 = &((*_3).1: usize);
+        _16 = &_15;
         StorageLive(_17);
-        _17 = _5;
-        _18 = &_17;
-        StorageLive(_19);
-        StorageLive(_20);
-        _19 = _7;
-        _20 = _17;
-        StorageLive(_21);
-        _21 = (*_19);
-        StorageLive(_22);
-        _22 = (*_20);
-        _23 = Le(move _21, move _22);
-        StorageDead(_22);
-        StorageDead(_21);
-        StorageDead(_20);
-        StorageDead(_19);
-        switchInt(move _23) -> [0: bb3, otherwise: bb8];
+        _17 = ((*_3).3: usize);
+        StorageLive(_18);
+        _18 = ((*_3).1: usize);
+        _19 = Le(move _17, move _18);
+        StorageDead(_18);
+        StorageDead(_17);
+        switchInt(move _19) -> [0: bb3, otherwise: bb8];
     }
 
     bb3: {
-        StorageDead(_17);
-        StorageDead(_18);
         StorageDead(_16);
+        StorageDead(_14);
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_31);
-        StorageLive(_24);
-        _24 = &_6;
-        StorageLive(_26);
-        StorageLive(_25);
-        _25 = _4;
-        _26 = &_25;
-        StorageLive(_27);
-        StorageLive(_28);
-        _27 = _6;
-        _28 = _25;
-        StorageLive(_29);
-        _29 = (*_27);
-        StorageLive(_30);
-        _30 = (*_28);
-        _31 = Le(move _29, move _30);
-        StorageDead(_30);
-        StorageDead(_29);
-        StorageDead(_28);
-        StorageDead(_27);
-        switchInt(move _31) -> [0: bb5, otherwise: bb6];
+        StorageLive(_23);
+        StorageLive(_20);
+        _20 = &_6;
+        StorageLive(_22);
+        _21 = &((*_3).0: usize);
+        _22 = &_21;
+        _23 = Le(_12, _11);
+        switchInt(move _23) -> [0: bb5, otherwise: bb6];
     }
 
     bb5: {
-        StorageDead(_25);
-        StorageDead(_26);
-        StorageDead(_24);
+        StorageDead(_22);
+        StorageDead(_20);
         _0 = const false;
         goto -> bb7;
     }
 
     bb6: {
-        StorageDead(_25);
+        StorageDead(_22);
+        StorageDead(_20);
+        StorageLive(_24);
+        _24 = &_5;
+        StorageLive(_26);
+        _25 = &((*_3).3: usize);
+        _26 = &_25;
+        StorageLive(_27);
+        _27 = ((*_3).1: usize);
+        StorageLive(_28);
+        _28 = ((*_3).3: usize);
+        _0 = Le(move _27, move _28);
+        StorageDead(_28);
+        StorageDead(_27);
         StorageDead(_26);
         StorageDead(_24);
-        StorageLive(_32);
-        _32 = &_5;
-        StorageLive(_34);
-        StorageLive(_33);
-        _33 = _7;
-        _34 = &_33;
-        StorageLive(_35);
-        StorageLive(_36);
-        _35 = _5;
-        _36 = _33;
-        StorageLive(_37);
-        _37 = (*_35);
-        StorageLive(_38);
-        _38 = (*_36);
-        _0 = Le(move _37, move _38);
-        StorageDead(_38);
-        StorageDead(_37);
-        StorageDead(_36);
-        StorageDead(_35);
-        StorageDead(_33);
-        StorageDead(_34);
-        StorageDead(_32);
         goto -> bb7;
     }
 
     bb7: {
-        StorageDead(_31);
+        StorageDead(_23);
         goto -> bb9;
     }
 
     bb8: {
-        StorageDead(_17);
-        StorageDead(_18);
         StorageDead(_16);
+        StorageDead(_14);
         _0 = const true;
         goto -> bb9;
     }
 
     bb9: {
-        StorageDead(_23);
-        StorageDead(_15);
-        StorageDead(_7);
-        StorageDead(_6);
-        StorageDead(_5);
-        StorageDead(_4);
+        StorageDead(_19);
+        StorageDead(_13);
         return;
     }
 }
diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
index 1be2ce8d0bb..0dfe8781c18 100644
--- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
@@ -247,7 +247,8 @@
           StorageLive(_21);
           _21 = &_20;
           StorageLive(_22);
-          _22 = (*_20);
+-         _22 = (*_20);
++         _22 = _19;
           StorageLive(_23);
           StorageLive(_24);
           _24 = _21;
@@ -394,7 +395,8 @@
           StorageLive(_62);
           _62 = &_61;
           StorageLive(_63);
-          _63 = (*_61);
+-         _63 = (*_61);
++         _63 = _60;
           StorageLive(_64);
           StorageLive(_65);
           _65 = ();
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
index 1e6a168f756..21486a8616a 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
@@ -260,7 +260,8 @@
           StorageLive(_20);
           _20 = &_19;
           StorageLive(_21);
-          _21 = (*_19);
+-         _21 = (*_19);
++         _21 = _18;
           StorageLive(_22);
           StorageLive(_23);
           _23 = _20;
@@ -429,7 +430,8 @@
           StorageLive(_67);
           _67 = &_66;
           StorageLive(_68);
-          _68 = (*_66);
+-         _68 = (*_66);
++         _68 = _65;
           StorageLive(_69);
           StorageLive(_70);
           _70 = ();
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
index 2dda771ba7d..e0b0d699420 100644
--- a/tests/mir-opt/reference_prop.rs
+++ b/tests/mir-opt/reference_prop.rs
@@ -49,7 +49,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) {
         // CHECK: [[a:_.*]] = const 5_usize;
         // CHECK: [[b:_.*]] = &[[a]];
         // CHECK: [[d:_.*]] = &[[b]];
-        // CHECK: [[c:_.*]] = (*[[b]]);
+        // CHECK: [[c:_.*]] = [[a]];
 
         let a = 5_usize;
         let b = &a;
@@ -138,8 +138,7 @@ fn reference_propagation<'a, T: Copy>(single: &'a T, mut multiple: &'a T) {
         // CHECK: [[a:_.*]] = const 5_usize;
         // CHECK: [[b:_.*]] = &[[a]];
         // CHECK: [[d:_.*]] = &[[b]];
-        // FIXME this could be [[a]]
-        // CHECK: [[c:_.*]] = (*[[b]]);
+        // CHECK: [[c:_.*]] = [[a]];
 
         let a = 5_usize;
         let b = &a;
@@ -363,7 +362,7 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con
         // CHECK: [[a:_.*]] = const 5_usize;
         // CHECK: [[b:_.*]] = &raw const [[a]];
         // CHECK: [[d:_.*]] = &[[b]];
-        // CHECK: [[c:_.*]] = (*[[b]]);
+        // CHECK: [[c:_.*]] = [[a]];
 
         let a = 5_usize;
         let b = &raw const a;
@@ -467,8 +466,7 @@ fn reference_propagation_const_ptr<T: Copy>(single: *const T, mut multiple: *con
         // CHECK: [[a:_.*]] = const 5_usize;
         // CHECK: [[b:_.*]] = &raw const [[a]];
         // CHECK: [[d:_.*]] = &[[b]];
-        // FIXME this could be [[a]]
-        // CHECK: [[c:_.*]] = (*[[b]]);
+        // CHECK: [[c:_.*]] = [[a]];
 
         let a = 5_usize;
         let b = &raw const a;