about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ich/impls_mir.rs3
-rw-r--r--src/librustc/mir/mod.rs8
-rw-r--r--src/librustc/mir/visit.rs1
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc/ty/context.rs7
-rw-r--r--src/librustc_codegen_ssa/mir/statement.rs1
-rw-r--r--src/librustc_mir/borrow_check/borrow_set.rs28
-rw-r--r--src/librustc_mir/borrow_check/mod.rs11
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/renumber.rs14
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs1
-rw-r--r--src/librustc_mir/build/cfg.rs26
-rw-r--r--src/librustc_mir/build/scope.rs297
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs97
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs1
-rw-r--r--src/librustc_mir/interpret/step.rs1
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs1
-rw-r--r--src/librustc_mir/transform/cleanup_post_borrowck.rs109
-rw-r--r--src/librustc_mir/transform/erase_regions.rs6
-rw-r--r--src/librustc_mir/transform/mod.rs3
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs1
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs1
-rw-r--r--src/librustc_mir/transform/remove_noop_landing_pads.rs5
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs1
-rw-r--r--src/librustc_passes/mir_stats.rs1
-rw-r--r--src/test/mir-opt/end_region_1.rs42
-rw-r--r--src/test/mir-opt/end_region_2.rs81
-rw-r--r--src/test/mir-opt/end_region_3.rs81
-rw-r--r--src/test/mir-opt/end_region_4.rs83
-rw-r--r--src/test/mir-opt/end_region_5.rs77
-rw-r--r--src/test/mir-opt/end_region_6.rs83
-rw-r--r--src/test/mir-opt/end_region_7.rs91
-rw-r--r--src/test/mir-opt/end_region_8.rs83
-rw-r--r--src/test/mir-opt/end_region_9.rs97
-rw-r--r--src/test/mir-opt/end_region_cyclic.rs141
-rw-r--r--src/test/mir-opt/end_region_destruction_extents_1.rs154
-rw-r--r--src/test/mir-opt/issue-43457.rs55
-rw-r--r--src/test/mir-opt/issue-49232.rs41
-rw-r--r--src/test/mir-opt/loop_test.rs2
-rw-r--r--src/test/run-pass/issues/issue-16671.rs2
-rw-r--r--src/test/ui/borrowck/immutable-arg.rs2
-rw-r--r--src/test/ui/issues/issue-45697-1.rs2
-rw-r--r--src/test/ui/issues/issue-45697.rs2
-rw-r--r--src/test/ui/issues/issue-46023.rs2
-rw-r--r--src/test/ui/issues/issue-46471-1.rs2
-rw-r--r--src/test/ui/issues/issue-46471.rs2
-rw-r--r--src/test/ui/issues/issue-46472.rs2
-rw-r--r--src/test/ui/moves/moves-based-on-type-tuple.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-uninitialized.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-with-fragment.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs2
-rw-r--r--src/test/ui/nll/maybe-initialized-drop.rs2
53 files changed, 207 insertions, 1560 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index d6ad74f16a9..d98bb82aaba 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -217,9 +217,6 @@ for mir::StatementKind<'gcx> {
             mir::StatementKind::StorageDead(ref place) => {
                 place.hash_stable(hcx, hasher);
             }
-            mir::StatementKind::EndRegion(ref region_scope) => {
-                region_scope.hash_stable(hcx, hasher);
-            }
             mir::StatementKind::EscapeToRaw(ref place) => {
                 place.hash_stable(hcx, hasher);
             }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index d8e45c881f5..a9ea1c9a109 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -15,7 +15,6 @@
 use hir::def::CtorKind;
 use hir::def_id::DefId;
 use hir::{self, HirId, InlineAsm};
-use middle::region;
 use mir::interpret::{ConstValue, EvalErrorKind, Scalar};
 use mir::visit::MirVisitable;
 use rustc_apfloat::ieee::{Double, Single};
@@ -1789,10 +1788,6 @@ pub enum StatementKind<'tcx> {
     /// for more details.
     EscapeToRaw(Operand<'tcx>),
 
-    /// Mark one terminating point of a region scope (i.e. static region).
-    /// (The starting point(s) arise implicitly from borrows.)
-    EndRegion(region::Scope),
-
     /// Encodes a user's type ascription. These need to be preserved
     /// intact so that NLL can respect them. For example:
     ///
@@ -1846,8 +1841,6 @@ impl<'tcx> Debug for Statement<'tcx> {
         match self.kind {
             Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
             FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
-            // (reuse lifetime rendering policy from ppaux.)
-            EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
             Retag { fn_entry, ref place } =>
                 write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place),
             EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
@@ -3028,7 +3021,6 @@ EnumTypeFoldableImpl! {
         (StatementKind::InlineAsm) { asm, outputs, inputs },
         (StatementKind::Retag) { fn_entry, place },
         (StatementKind::EscapeToRaw)(place),
-        (StatementKind::EndRegion)(a),
         (StatementKind::AscribeUserType)(a, v, b),
         (StatementKind::Nop),
     }
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 2a994ee0509..0c9b06a8d8c 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -377,7 +377,6 @@ macro_rules! make_mir_visitor {
                             location
                         );
                     }
-                    StatementKind::EndRegion(_) => {}
                     StatementKind::SetDiscriminant{ ref $($mutability)* place, .. } => {
                         self.visit_place(
                             place,
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index c620e092f36..3fd22793a08 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1149,8 +1149,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path
     identify_regions: bool = (false, parse_bool, [UNTRACKED],
         "make unnamed regions display as '# (where # is some non-ident unique id)"),
-    emit_end_regions: bool = (false, parse_bool, [UNTRACKED],
-        "emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
     borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED],
         "select which borrowck is used (`ast`, `mir`, `migrate`, or `compare`)"),
     two_phase_borrows: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index a8ce52a8e15..1b947c276f3 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1540,13 +1540,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    /// Should we emit EndRegion MIR statements? These are consumed by
-    /// MIR borrowck, but not when NLL is used.
-    pub fn emit_end_regions(self) -> bool {
-        self.sess.opts.debugging_opts.emit_end_regions ||
-            self.use_mir_borrowck()
-    }
-
     #[inline]
     pub fn local_crate_exports_generics(self) -> bool {
         debug_assert!(self.sess.opts.share_generics());
diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs
index a69474142ab..0d058c85f33 100644
--- a/src/librustc_codegen_ssa/mir/statement.rs
+++ b/src/librustc_codegen_ssa/mir/statement.rs
@@ -105,7 +105,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 bx
             }
             mir::StatementKind::FakeRead(..) |
-            mir::StatementKind::EndRegion(..) |
             mir::StatementKind::Retag { .. } |
             mir::StatementKind::EscapeToRaw { .. } |
             mir::StatementKind::AscribeUserType(..) |
diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs
index c432826dca8..fd7dc7fc4bd 100644
--- a/src/librustc_mir/borrow_check/borrow_set.rs
+++ b/src/librustc_mir/borrow_check/borrow_set.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use borrow_check::place_ext::PlaceExt;
+use borrow_check::nll::ToRegionVid;
 use dataflow::indexes::BorrowIndex;
 use dataflow::move_paths::MoveData;
 use rustc::mir::traversal;
@@ -16,7 +17,7 @@ use rustc::mir::visit::{
     PlaceContext, Visitor, NonUseContext, MutatingUseContext, NonMutatingUseContext
 };
 use rustc::mir::{self, Location, Mir, Place, Local};
-use rustc::ty::{Region, TyCtxt};
+use rustc::ty::{RegionVid, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::bit_set::BitSet;
@@ -42,7 +43,7 @@ crate struct BorrowSet<'tcx> {
 
     /// Every borrow has a region; this maps each such regions back to
     /// its borrow-indexes.
-    crate region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+    crate region_map: FxHashMap<RegionVid, FxHashSet<BorrowIndex>>,
 
     /// Map from local to all the borrows on that local
     crate local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
@@ -77,7 +78,7 @@ crate struct BorrowData<'tcx> {
     /// What kind of borrow this is
     crate kind: mir::BorrowKind,
     /// The region for which this borrow is live
-    crate region: Region<'tcx>,
+    crate region: RegionVid,
     /// Place from which we are borrowing
     crate borrowed_place: mir::Place<'tcx>,
     /// Place to which the borrow was stored
@@ -92,13 +93,7 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> {
             mir::BorrowKind::Unique => "uniq ",
             mir::BorrowKind::Mut { .. } => "mut ",
         };
-        let region = self.region.to_string();
-        let separator = if !region.is_empty() {
-            " "
-        } else {
-            ""
-        };
-        write!(w, "&{}{}{}{:?}", region, separator, kind, self.borrowed_place)
+        write!(w, "&{:?} {}{:?}", self.region, kind, self.borrowed_place)
     }
 }
 
@@ -189,7 +184,7 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>,
     location_map: FxHashMap<Location, BorrowIndex>,
     activation_map: FxHashMap<Location, Vec<BorrowIndex>>,
-    region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>,
+    region_map: FxHashMap<RegionVid, FxHashSet<BorrowIndex>>,
     local_map: FxHashMap<mir::Local, FxHashSet<BorrowIndex>>,
 
     /// When we encounter a 2-phase borrow statement, it will always
@@ -219,6 +214,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
                 return;
             }
 
+            let region = region.to_region_vid();
+
             let borrow = BorrowData {
                 kind,
                 region,
@@ -230,7 +227,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
             let idx = self.idx_vec.push(borrow);
             self.location_map.insert(location, idx);
 
-            self.insert_as_pending_if_two_phase(location, &assigned_place, region, kind, idx);
+            self.insert_as_pending_if_two_phase(location, &assigned_place, kind, idx);
 
             self.region_map.entry(region).or_default().insert(idx);
             if let Some(local) = borrowed_place.root_local() {
@@ -314,7 +311,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
             let borrow_data = &self.idx_vec[borrow_index];
             assert_eq!(borrow_data.reserve_location, location);
             assert_eq!(borrow_data.kind, kind);
-            assert_eq!(borrow_data.region, region);
+            assert_eq!(borrow_data.region, region.to_region_vid());
             assert_eq!(borrow_data.borrowed_place, *place);
         }
 
@@ -347,13 +344,12 @@ impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> {
         &mut self,
         start_location: Location,
         assigned_place: &mir::Place<'tcx>,
-        region: Region<'tcx>,
         kind: mir::BorrowKind,
         borrow_index: BorrowIndex,
     ) {
         debug!(
-            "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?}, {:?})",
-            start_location, assigned_place, region, borrow_index,
+            "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?})",
+            start_location, assigned_place, borrow_index,
         );
 
         if !self.allow_two_phase_borrow(kind) {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index f0d3b863f78..76ba6ae5de6 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -14,7 +14,6 @@ use borrow_check::nll::region_infer::RegionInferenceContext;
 use rustc::hir;
 use rustc::hir::Node;
 use rustc::hir::def_id::DefId;
-use rustc::hir::map::definitions::DefPathData;
 use rustc::infer::InferCtxt;
 use rustc::lint::builtin::UNUSED_MUT;
 use rustc::middle::borrowck::SignalledError;
@@ -162,10 +161,6 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         move_data: move_data,
         param_env: param_env,
     };
-    let body_id = match tcx.def_key(def_id).disambiguated_data.data {
-        DefPathData::StructCtor | DefPathData::EnumVariant(_) => None,
-        _ => Some(tcx.hir.body_owned_by(id)),
-    };
 
     let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len());
     let mut flow_inits = FlowAtLocation::new(do_dataflow(
@@ -212,7 +207,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         id,
         &attributes,
         &dead_unwinds,
-        Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set),
+        Borrows::new(tcx, mir, regioncx.clone(), &borrow_set),
         |rs, i| DebugFormatted::new(&rs.location(i)),
     ));
     let flow_uninits = FlowAtLocation::new(do_dataflow(
@@ -592,10 +587,6 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                     self.consume_operand(context, (input, span), flow_state);
                 }
             }
-            StatementKind::EndRegion(ref _rgn) => {
-                // ignored when consuming results (update to
-                // flow_state already handled).
-            }
             StatementKind::Nop
             | StatementKind::AscribeUserType(..)
             | StatementKind::Retag { .. }
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 2bf531d1d3e..bb9a29b055b 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -206,7 +206,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let mir = self.mir;
         let tcx = self.infcx.tcx;
 
-        let borrow_region_vid = regioncx.to_region_vid(borrow.region);
+        let borrow_region_vid = borrow.region;
         debug!(
             "explain_why_borrow_contains_point: borrow_region_vid={:?}",
             borrow_region_vid
diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 576509c0fdd..8af23a8813a 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -132,8 +132,6 @@ impl<'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx, 'gcx> {
                     self.consume_operand(context, input);
                 }
             }
-            // EndRegion matters to older NLL/MIR AST borrowck, not to alias NLL
-            StatementKind::EndRegion(..) |
             StatementKind::Nop |
             StatementKind::AscribeUserType(..) |
             StatementKind::Retag { .. } |
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 363afb87ed9..e9f749ac092 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -10,7 +10,7 @@
 
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
-use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind, UserTypeAnnotation};
+use rustc::mir::{Location, Mir, UserTypeAnnotation};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 
@@ -119,16 +119,4 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
 
         debug!("visit_closure_substs: substs={:?}", substs);
     }
-
-    fn visit_statement(
-        &mut self,
-        block: BasicBlock,
-        statement: &mut Statement<'tcx>,
-        location: Location,
-    ) {
-        if let StatementKind::EndRegion(_) = statement.kind {
-            statement.kind = StatementKind::Nop;
-        }
-        self.super_statement(block, statement, location);
-    }
 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 06dfd4bc2cc..b978d8c9d0a 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -1314,7 +1314,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             | StatementKind::StorageLive(..)
             | StatementKind::StorageDead(..)
             | StatementKind::InlineAsm { .. }
-            | StatementKind::EndRegion(_)
             | StatementKind::Retag { .. }
             | StatementKind::EscapeToRaw { .. }
             | StatementKind::Nop => {}
diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs
index 619ebb1675c..2efb75c232d 100644
--- a/src/librustc_mir/build/cfg.rs
+++ b/src/librustc_mir/build/cfg.rs
@@ -14,9 +14,7 @@
 //! Routines for manipulating the control-flow graph.
 
 use build::CFG;
-use rustc::middle::region;
 use rustc::mir::*;
-use rustc::ty::TyCtxt;
 
 impl<'tcx> CFG<'tcx> {
     pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
@@ -45,30 +43,6 @@ impl<'tcx> CFG<'tcx> {
         self.block_data_mut(block).statements.push(statement);
     }
 
-    pub fn push_end_region<'a, 'gcx:'a+'tcx>(&mut self,
-                                             tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                             block: BasicBlock,
-                                             source_info: SourceInfo,
-                                             region_scope: region::Scope) {
-        if tcx.emit_end_regions() {
-            if let region::ScopeData::CallSite = region_scope.data {
-                // The CallSite scope (aka the root scope) is sort of weird, in that it is
-                // supposed to "separate" the "interior" and "exterior" of a closure. Being
-                // that, it is not really a part of the region hierarchy, but for some
-                // reason it *is* considered a part of it.
-                //
-                // It should die a hopefully painful death with NLL, so let's leave this hack
-                // for now so that nobody can complain about soundness.
-                return
-            }
-
-            self.push(block, Statement {
-                source_info,
-                kind: StatementKind::EndRegion(region_scope),
-            });
-        }
-    }
-
     pub fn push_assign(&mut self,
                        block: BasicBlock,
                        source_info: SourceInfo,
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 99badd5a03f..2a11f24095b 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -90,12 +90,13 @@ should go to.
 use build::{BlockAnd, BlockAndExtension, Builder, CFG};
 use hair::LintLevel;
 use rustc::middle::region;
-use rustc::ty::{Ty, TyCtxt};
+use rustc::ty::Ty;
 use rustc::hir;
 use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::mir::*;
 use syntax_pos::{Span};
 use rustc_data_structures::fx::FxHashMap;
+use std::collections::hash_map::Entry;
 
 #[derive(Debug)]
 pub struct Scope<'tcx> {
@@ -224,7 +225,7 @@ impl<'tcx> Scope<'tcx> {
     /// Should always be run for all inner scopes when a drop is pushed into some scope enclosing a
     /// larger extent of code.
     ///
-    /// `storage_only` controls whether to invalidate only drop paths run `StorageDead`.
+    /// `storage_only` controls whether to invalidate only drop paths that run `StorageDead`.
     /// `this_scope_only` controls whether to invalidate only drop paths that refer to the current
     /// top-of-scope (as opposed to dependent scopes).
     fn invalidate_cache(&mut self, storage_only: bool, this_scope_only: bool) {
@@ -242,8 +243,8 @@ impl<'tcx> Scope<'tcx> {
         }
 
         if !storage_only && !this_scope_only {
-            for dropdata in &mut self.drops {
-                if let DropKind::Value { ref mut cached_block } = dropdata.kind {
+            for drop_data in &mut self.drops {
+                if let DropKind::Value { ref mut cached_block } = drop_data.kind {
                     cached_block.invalidate();
                 }
             }
@@ -323,7 +324,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 let parent_hir_id =
                     tcx.hir.definitions().node_to_hir_id(
                         self.source_scope_local_data[source_scope].lint_root
-                            );
+                    );
                 let current_hir_id =
                     tcx.hir.definitions().node_to_hir_id(node_id);
                 sets.lint_level_set(parent_hir_id) ==
@@ -333,7 +334,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             if !same_lint_scopes {
                 self.source_scope =
                     self.new_source_scope(region_scope.1.span, lint_level,
-                                              None);
+                                          None);
             }
         }
         self.push_scope(region_scope);
@@ -381,15 +382,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let scope = self.scopes.pop().unwrap();
         assert_eq!(scope.region_scope, region_scope.0);
 
-        self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope);
-        let resume_block = self.resume_block();
-        unpack!(block = build_scope_drops(&mut self.cfg,
-                                          resume_block,
-                                          &scope,
-                                          &self.scopes,
-                                          block,
-                                          self.arg_count,
-                                          false));
+        let unwind_to = self.scopes.last().and_then(|next_scope| {
+            next_scope.cached_unwind.get(false)
+        }).unwrap_or_else(|| self.resume_block());
+
+        unpack!(block = build_scope_drops(
+            &mut self.cfg,
+            &scope,
+            block,
+            unwind_to,
+            self.arg_count,
+            false,
+        ));
 
         block.unit()
     }
@@ -397,8 +401,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
     /// Branch out of `block` to `target`, exiting all scopes up to
     /// and including `region_scope`.  This will insert whatever drops are
-    /// needed, as well as tracking this exit for the SEME region. See
-    /// module comment for details.
+    /// needed. See module comment for details.
     pub fn exit_scope(&mut self,
                       span: Span,
                       region_scope: (region::Scope, SourceInfo),
@@ -416,41 +419,51 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
         // If we are emitting a `drop` statement, we need to have the cached
         // diverge cleanup pads ready in case that drop panics.
-        let may_panic = self.scopes[(len - scope_count)..].iter()
-            .any(|s| s.drops.iter().any(|s| s.kind.may_panic()));
+        let may_panic = self.scopes[(len - scope_count)..].iter().any(|s| s.needs_cleanup);
         if may_panic {
             self.diverge_cleanup();
         }
 
-        {
-        let resume_block = self.resume_block();
-        let mut rest = &mut self.scopes[(len - scope_count)..];
-        while let Some((scope, rest_)) = {rest}.split_last_mut() {
-            rest = rest_;
-            block = if let Some(&e) = scope.cached_exits.get(&(target, region_scope.0)) {
-                self.cfg.terminate(block, scope.source_info(span),
-                                   TerminatorKind::Goto { target: e });
-                return;
-            } else {
-                let b = self.cfg.start_new_block();
-                self.cfg.terminate(block, scope.source_info(span),
-                                   TerminatorKind::Goto { target: b });
-                scope.cached_exits.insert((target, region_scope.0), b);
-                b
+        let mut scopes = self.scopes[(len - scope_count - 1)..].iter_mut().rev();
+        let mut scope = scopes.next().unwrap();
+        for next_scope in scopes {
+            if scope.drops.is_empty() {
+                scope = next_scope;
+                continue;
+            }
+            let source_info = scope.source_info(span);
+            block = match scope.cached_exits.entry((target, region_scope.0)) {
+                Entry::Occupied(e) => {
+                    self.cfg.terminate(block, source_info,
+                                    TerminatorKind::Goto { target: *e.get() });
+                    return;
+                }
+                Entry::Vacant(v) => {
+                    let b = self.cfg.start_new_block();
+                    self.cfg.terminate(block, source_info,
+                                    TerminatorKind::Goto { target: b });
+                    v.insert(b);
+                    b
+                }
             };
 
-            // End all regions for scopes out of which we are breaking.
-            self.cfg.push_end_region(self.hir.tcx(), block, region_scope.1, scope.region_scope);
+            let unwind_to = next_scope.cached_unwind.get(false).unwrap_or_else(|| {
+                debug_assert!(!may_panic, "cached block not present?");
+                START_BLOCK
+            });
 
-            unpack!(block = build_scope_drops(&mut self.cfg,
-                                              resume_block,
-                                              scope,
-                                              rest,
-                                              block,
-                                              self.arg_count,
-                                              false));
-        }
+            unpack!(block = build_scope_drops(
+                &mut self.cfg,
+                scope,
+                block,
+                unwind_to,
+                self.arg_count,
+                false,
+            ));
+
+            scope = next_scope;
         }
+
         let scope = &self.scopes[len - scope_count];
         self.cfg.terminate(block, scope.source_info(span),
                            TerminatorKind::Goto { target });
@@ -465,20 +478,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             return None;
         }
 
-        // Fill in the cache
+        // Fill in the cache for unwinds
         self.diverge_cleanup_gen(true);
 
         let src_info = self.scopes[0].source_info(self.fn_span);
+        let resume_block = self.resume_block();
+        let mut scopes = self.scopes.iter_mut().rev().peekable();
         let mut block = self.cfg.start_new_block();
         let result = block;
-        let resume_block = self.resume_block();
-        let mut rest = &mut self.scopes[..];
 
-        while let Some((scope, rest_)) = {rest}.split_last_mut() {
-            rest = rest_;
+        while let Some(scope) = scopes.next() {
             if !scope.needs_cleanup {
                 continue;
             }
+
             block = if let Some(b) = scope.cached_generator_drop {
                 self.cfg.terminate(block, src_info,
                                    TerminatorKind::Goto { target: b });
@@ -491,16 +504,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 b
             };
 
-            // End all regions for scopes out of which we are breaking.
-            self.cfg.push_end_region(self.hir.tcx(), block, src_info, scope.region_scope);
-
-            unpack!(block = build_scope_drops(&mut self.cfg,
-                                              resume_block,
-                                              scope,
-                                              rest,
-                                              block,
-                                              self.arg_count,
-                                              true));
+            let unwind_to = scopes.peek().as_ref().map(|scope| {
+                scope.cached_unwind.get(true).unwrap_or_else(|| {
+                    span_bug!(src_info.span, "cached block not present?")
+                })
+            }).unwrap_or(resume_block);
+
+            unpack!(block = build_scope_drops(
+                &mut self.cfg,
+                scope,
+                block,
+                unwind_to,
+                self.arg_count,
+                true,
+            ));
         }
 
         self.cfg.terminate(block, src_info, TerminatorKind::GeneratorDrop);
@@ -510,9 +527,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
     /// Creates a new source scope, nested in the current one.
     pub fn new_source_scope(&mut self,
-                                span: Span,
-                                lint_level: LintLevel,
-                                safety: Option<Safety>) -> SourceScope {
+                            span: Span,
+                            lint_level: LintLevel,
+                            safety: Option<Safety>) -> SourceScope {
         let parent = self.source_scope;
         debug!("new_source_scope({:?}, {:?}, {:?}) - parent({:?})={:?}",
                span, lint_level, safety,
@@ -749,8 +766,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// Creates a path that performs all required cleanup for unwinding.
     ///
     /// This path terminates in Resume. Returns the start of the path.
-    /// See module comment for more details. None indicates there’s no
-    /// cleanup to do at this point.
+    /// See module comment for more details.
     pub fn diverge_cleanup(&mut self) -> BasicBlock {
         self.diverge_cleanup_gen(false)
     }
@@ -772,11 +788,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     }
 
     fn diverge_cleanup_gen(&mut self, generator_drop: bool) -> BasicBlock {
-        // To start, create the resume terminator.
-        let mut target = self.resume_block();
-
-        let Builder { ref mut cfg, ref mut scopes, .. } = *self;
-
         // Build up the drops in **reverse** order. The end result will
         // look like:
         //
@@ -788,11 +799,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         // store caches. If everything is cached, we'll just walk right
         // to left reading the cached results but never created anything.
 
-        if scopes.iter().any(|scope| scope.needs_cleanup) {
-            for scope in scopes.iter_mut() {
-                target = build_diverge_scope(self.hir.tcx(), cfg, scope.region_scope_span,
-                                             scope, target, generator_drop);
-            }
+        // Find the last cached block
+        let (mut target, first_uncached) = if let Some(cached_index) = self.scopes.iter()
+            .rposition(|scope| scope.cached_unwind.get(generator_drop).is_some()) {
+            (self.scopes[cached_index].cached_unwind.get(generator_drop).unwrap(), cached_index + 1)
+        } else {
+            (self.resume_block(), 0)
+        };
+
+        for scope in self.scopes[first_uncached..].iter_mut() {
+            target = build_diverge_scope(&mut self.cfg, scope.region_scope_span,
+                                         scope, target, generator_drop);
         }
 
         target
@@ -866,64 +883,62 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 }
 
 /// Builds drops for pop_scope and exit_scope.
-fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
-                           resume_block: BasicBlock,
-                           scope: &Scope<'tcx>,
-                           earlier_scopes: &[Scope<'tcx>],
-                           mut block: BasicBlock,
-                           arg_count: usize,
-                           generator_drop: bool)
-                           -> BlockAnd<()> {
-    debug!("build_scope_drops({:?} -> {:?})", block, scope);
-    let mut iter = scope.drops.iter().rev();
-    while let Some(drop_data) = iter.next() {
+fn build_scope_drops<'tcx>(
+    cfg: &mut CFG<'tcx>,
+    scope: &Scope<'tcx>,
+    mut block: BasicBlock,
+    last_unwind_to: BasicBlock,
+    arg_count: usize,
+    generator_drop: bool,
+) -> BlockAnd<()> {
+    debug!("build_scope_drops({:?} -> {:?}", block, scope);
+
+    // Build up the drops in evaluation order. The end result will
+    // look like:
+    //
+    // [SDs, drops[n]] --..> [SDs, drop[1]] -> [SDs, drop[0]] -> [[SDs]]
+    //               |                    |                 |
+    //               :                    |                 |
+    //                                    V                 V
+    // [drop[n]] -...-> [drop[1]] ------> [drop[0]] ------> [last_unwind_to]
+    //
+    // The horizontal arrows represent the execution path when the drops return
+    // successfully. The downwards arrows represent the execution path when the
+    // drops panic (panicking while unwinding will abort, so there's no need for
+    // another set of arrows). The drops for the unwind path should have already
+    // been generated by `diverge_cleanup_gen`.
+    //
+    // The code in this function reads from right to left.
+    // Storage dead drops have to be done left to right (since we can only push
+    // to the end of a Vec). So, we find the next drop and then call
+    // push_storage_deads which will iterate backwards through them so that
+    // they are added in the correct order.
+
+    let mut unwind_blocks = scope.drops.iter().rev().filter_map(|drop_data| {
+        if let DropKind::Value { cached_block } = drop_data.kind {
+            Some(cached_block.get(generator_drop).unwrap_or_else(|| {
+                span_bug!(drop_data.span, "cached block not present?")
+            }))
+        } else {
+            None
+        }
+    });
+
+    // When we unwind from a drop, we start cleaning up from the next one, so
+    // we don't need this block.
+    unwind_blocks.next();
+
+    for drop_data in scope.drops.iter().rev() {
         let source_info = scope.source_info(drop_data.span);
         match drop_data.kind {
             DropKind::Value { .. } => {
-                // Try to find the next block with its cached block for us to
-                // diverge into, either a previous block in this current scope or
-                // the top of the previous scope.
-                //
-                // If it wasn't for EndRegion, we could just chain all the DropData
-                // together and pick the first DropKind::Value. Please do that
-                // when we replace EndRegion with NLL.
-                let on_diverge = iter.clone().filter_map(|dd| {
-                    match dd.kind {
-                        DropKind::Value { cached_block } => Some(cached_block),
-                        DropKind::Storage => None
-                    }
-                }).next().or_else(|| {
-                    if earlier_scopes.iter().any(|scope| scope.needs_cleanup) {
-                        // If *any* scope requires cleanup code to be run,
-                        // we must use the cached unwind from the *topmost*
-                        // scope, to ensure all EndRegions from surrounding
-                        // scopes are executed before the drop code runs.
-                        Some(earlier_scopes.last().unwrap().cached_unwind)
-                    } else {
-                        // We don't need any further cleanup, so return None
-                        // to avoid creating a landing pad. We can skip
-                        // EndRegions because all local regions end anyway
-                        // when the function unwinds.
-                        //
-                        // This is an important optimization because LLVM is
-                        // terrible at optimizing landing pads. FIXME: I think
-                        // it would be cleaner and better to do this optimization
-                        // in SimplifyCfg instead of here.
-                        None
-                    }
-                });
-
-                let on_diverge = on_diverge.map(|cached_block| {
-                    cached_block.get(generator_drop).unwrap_or_else(|| {
-                        span_bug!(drop_data.span, "cached block not present?")
-                    })
-                });
+                let unwind_to = unwind_blocks.next().unwrap_or(last_unwind_to);
 
                 let next = cfg.start_new_block();
                 cfg.terminate(block, source_info, TerminatorKind::Drop {
                     location: drop_data.location.clone(),
                     target: next,
-                    unwind: Some(on_diverge.unwrap_or(resume_block))
+                    unwind: Some(unwind_to)
                 });
                 block = next;
             }
@@ -950,21 +965,17 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
     block.unit()
 }
 
-fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                       cfg: &mut CFG<'tcx>,
-                                       span: Span,
-                                       scope: &mut Scope<'tcx>,
-                                       mut target: BasicBlock,
-                                       generator_drop: bool)
-                                       -> BasicBlock
+fn build_diverge_scope<'tcx>(cfg: &mut CFG<'tcx>,
+                             span: Span,
+                             scope: &mut Scope<'tcx>,
+                             mut target: BasicBlock,
+                             generator_drop: bool)
+                             -> BasicBlock
 {
     // Build up the drops in **reverse** order. The end result will
     // look like:
     //
-    //    [EndRegion Block] -> [drops[n]] -...-> [drops[0]] -> [Free] -> [target]
-    //    |                                                         |
-    //    +---------------------------------------------------------+
-    //     code for scope
+    //    [drops[n]] -...-> [drops[0]] -> [target]
     //
     // The code in this function reads from right to left. At each
     // point, we check for cached blocks representing the
@@ -1009,21 +1020,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         };
     }
 
-    // Finally, push the EndRegion block, used by mir-borrowck, and set
-    // `cached_unwind` to point to it (Block becomes trivial goto after
-    // pass that removes all EndRegions).
-    target = {
-        let cached_block = scope.cached_unwind.ref_mut(generator_drop);
-        if let Some(cached_block) = *cached_block {
-            cached_block
-        } else {
-            let block = cfg.start_new_cleanup_block();
-            cfg.push_end_region(tcx, block, source_info(span), scope.region_scope);
-            cfg.terminate(block, source_info(span), TerminatorKind::Goto { target });
-            *cached_block = Some(block);
-            block
-        }
-    };
+    *scope.cached_unwind.ref_mut(generator_drop) = Some(target);
 
     debug!("build_diverge_scope({:?}, {:?}) = {:?}", scope, span, target);
 
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 811da9e1acc..27bc28ac81d 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -12,18 +12,13 @@ use borrow_check::borrow_set::{BorrowSet, BorrowData};
 use borrow_check::place_ext::PlaceExt;
 
 use rustc;
-use rustc::hir;
-use rustc::hir::def_id::DefId;
-use rustc::middle::region;
 use rustc::mir::{self, Location, Place, Mir};
 use rustc::ty::TyCtxt;
-use rustc::ty::{RegionKind, RegionVid};
-use rustc::ty::RegionKind::ReScope;
+use rustc::ty::RegionVid;
 
 use rustc_data_structures::bit_set::{BitSet, BitSetOperator};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc_data_structures::sync::Lrc;
 
 use dataflow::{BitDenotation, BlockSets, InitialFlow};
 pub use dataflow::indexes::BorrowIndex;
@@ -42,8 +37,6 @@ use std::rc::Rc;
 pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
-    scope_tree: Lrc<region::ScopeTree>,
-    root_scope: Option<region::Scope>,
 
     borrow_set: Rc<BorrowSet<'tcx>>,
     borrows_out_of_scope_at_location: FxHashMap<Location, Vec<BorrowIndex>>,
@@ -150,18 +143,8 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
         mir: &'a Mir<'tcx>,
         nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>,
-        def_id: DefId,
-        body_id: Option<hir::BodyId>,
         borrow_set: &Rc<BorrowSet<'tcx>>,
     ) -> Self {
-        let scope_tree = tcx.region_scope_tree(def_id);
-        let root_scope = body_id.map(|body_id| {
-            region::Scope {
-                id: tcx.hir.body(body_id).value.hir_id.local_id,
-                data: region::ScopeData::CallSite
-            }
-        });
-
         let mut borrows_out_of_scope_at_location = FxHashMap::default();
         for (borrow_index, borrow_data) in borrow_set.borrows.iter_enumerated() {
             let borrow_region = borrow_data.region.to_region_vid();
@@ -177,8 +160,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
             mir: mir,
             borrow_set: borrow_set.clone(),
             borrows_out_of_scope_at_location,
-            scope_tree,
-            root_scope,
             _nonlexical_regioncx: nonlexical_regioncx,
         }
     }
@@ -190,8 +171,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
     }
 
     /// Add all borrows to the kill set, if those borrows are out of scope at `location`.
-    /// That means either they went out of either a nonlexical scope, if we care about those
-    /// at the moment, or the location represents a lexical EndRegion
+    /// That means they went out of a nonlexical scope
     fn kill_loans_out_of_scope_at_location(&self,
                                            sets: &mut BlockSets<BorrowIndex>,
                                            location: Location) {
@@ -252,9 +232,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
         });
 
         match stmt.kind {
-            mir::StatementKind::EndRegion(_) => {
-            }
-
             mir::StatementKind::Assign(ref lhs, ref rhs) => {
                 // Make sure there are no remaining borrows for variables
                 // that are assigned over.
@@ -281,22 +258,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
                         panic!("could not find BorrowIndex for location {:?}", location);
                     });
 
-                    if let RegionKind::ReEmpty = region {
-                        // If the borrowed value dies before the borrow is used, the region for
-                        // the borrow can be empty. Don't track the borrow in that case.
-                        debug!("Borrows::statement_effect_on_borrows \
-                                location: {:?} stmt: {:?} has empty region, killing {:?}",
-                               location, stmt.kind, index);
-                        sets.kill(*index);
-                        return
-                    } else {
-                        debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}",
-                               location, stmt.kind);
-                    }
-
-                    assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| {
-                        panic!("could not find BorrowIndexs for region {:?}", region);
-                    }).contains(&index));
+                    assert!(self.borrow_set.region_map
+                        .get(&region.to_region_vid())
+                        .unwrap_or_else(|| {
+                            panic!("could not find BorrowIndexs for RegionVid {:?}", region);
+                        })
+                        .contains(&index)
+                    );
                     sets.gen(*index);
 
                     // Issue #46746: Two-phase borrows handles
@@ -353,52 +321,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
         self.kill_loans_out_of_scope_at_location(sets, location);
     }
 
-    fn terminator_effect(&self, sets: &mut BlockSets<BorrowIndex>, location: Location) {
-        debug!("Borrows::terminator_effect sets: {:?} location: {:?}", sets, location);
-
-        let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| {
-            panic!("could not find block at location {:?}", location);
-        });
-
-        let term = block.terminator();
-        match term.kind {
-            mir::TerminatorKind::Resume |
-            mir::TerminatorKind::Return |
-            mir::TerminatorKind::GeneratorDrop => {
-                // When we return from the function, then all `ReScope`-style regions
-                // are guaranteed to have ended.
-                // Normally, there would be `EndRegion` statements that come before,
-                // and hence most of these loans will already be dead -- but, in some cases
-                // like unwind paths, we do not always emit `EndRegion` statements, so we
-                // add some kills here as a "backup" and to avoid spurious error messages.
-                for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() {
-                    if let ReScope(scope) = borrow_data.region {
-                        // Check that the scope is not actually a scope from a function that is
-                        // a parent of our closure. Note that the CallSite scope itself is
-                        // *outside* of the closure, for some weird reason.
-                        if let Some(root_scope) = self.root_scope {
-                            if *scope != root_scope &&
-                                self.scope_tree.is_subscope_of(*scope, root_scope)
-                            {
-                                sets.kill(borrow_index);
-                            }
-                        }
-                    }
-                }
-            }
-            mir::TerminatorKind::Abort |
-            mir::TerminatorKind::SwitchInt {..} |
-            mir::TerminatorKind::Drop {..} |
-            mir::TerminatorKind::DropAndReplace {..} |
-            mir::TerminatorKind::Call {..} |
-            mir::TerminatorKind::Assert {..} |
-            mir::TerminatorKind::Yield {..} |
-            mir::TerminatorKind::Goto {..} |
-            mir::TerminatorKind::FalseEdges {..} |
-            mir::TerminatorKind::FalseUnwind {..} |
-            mir::TerminatorKind::Unreachable => {}
-        }
-    }
+    fn terminator_effect(&self, _: &mut BlockSets<BorrowIndex>, _: Location) {}
 
     fn propagate_call_return(&self,
                              _in_out: &mut BitSet<BorrowIndex>,
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 0e2376d201f..3796b1cc4b0 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -301,7 +301,6 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
                 span_bug!(stmt.source_info.span,
                           "SetDiscriminant should not exist during borrowck");
             }
-            StatementKind::EndRegion(..) |
             StatementKind::Retag { .. } |
             StatementKind::EscapeToRaw { .. } |
             StatementKind::AscribeUserType(..) |
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index ac13e5982da..8814118f65b 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -129,7 +129,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             }
 
             // Statements we do not track.
-            EndRegion(..) => {}
             AscribeUserType(..) => {}
 
             // Defined to do nothing. These are added by optimization passes, to avoid changing the
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index 4ebeebca227..3404772f825 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -112,7 +112,6 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
             StatementKind::SetDiscriminant { .. } |
             StatementKind::StorageLive(..) |
             StatementKind::StorageDead(..) |
-            StatementKind::EndRegion(..) |
             StatementKind::Retag { .. } |
             StatementKind::EscapeToRaw { .. } |
             StatementKind::AscribeUserType(..) |
diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs
index 98311444e28..c0edd3926d3 100644
--- a/src/librustc_mir/transform/cleanup_post_borrowck.rs
+++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs
@@ -10,111 +10,26 @@
 
 //! This module provides two passes:
 //!
-//!   - `CleanEndRegions`, that reduces the set of `EndRegion` statements
-//!     in the MIR.
-//!   - `CleanAscribeUserType`, that replaces all `AscribeUserType` statements
-//!     with `Nop`.
+//!   - [CleanAscribeUserType], that replaces all
+//!     [StatementKind::AscribeUserType] statements with [StatementKind::Nop].
+//!   - [CleanFakeReadsAndBorrows], that replaces all [FakeRead] statements and
+//!     borrows that are read by [FakeReadCause::ForMatchGuard] fake reads with
+//!     [StatementKind::Nop].
 //!
-//! The `CleanEndRegions` "pass" is actually implemented as two
+//! The [CleanFakeReadsAndBorrows] "pass" is actually implemented as two
 //! traversals (aka visits) of the input MIR. The first traversal,
-//! `GatherBorrowedRegions`, finds all of the regions in the MIR
-//! that are involved in a borrow.
-//!
-//! The second traversal, `DeleteTrivialEndRegions`, walks over the
-//! MIR and removes any `EndRegion` that is applied to a region that
-//! was not seen in the previous pass.
-//!
-//! The `CleanAscribeUserType` pass runs at a distinct time from the
-//! `CleanEndRegions` pass. It is important that the `CleanAscribeUserType`
-//! pass runs after the MIR borrowck so that the NLL type checker can
-//! perform the type assertion when it encounters the `AscribeUserType`
-//! statements.
+//! [DeleteAndRecordFakeReads], deletes the fake reads and finds the temporaries
+//! read by [ForMatchGuard] reads, and [DeleteFakeBorrows] deletes the
+//! initialization of those temporaries.
 
 use rustc_data_structures::fx::FxHashSet;
 
-use rustc::middle::region;
 use rustc::mir::{BasicBlock, FakeReadCause, Local, Location, Mir, Place};
-use rustc::mir::{Rvalue, Statement, StatementKind};
-use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
-use rustc::ty::{Ty, RegionKind, TyCtxt};
-use smallvec::smallvec;
+use rustc::mir::{Statement, StatementKind};
+use rustc::mir::visit::MutVisitor;
+use rustc::ty::TyCtxt;
 use transform::{MirPass, MirSource};
 
-pub struct CleanEndRegions;
-
-#[derive(Default)]
-struct GatherBorrowedRegions {
-    seen_regions: FxHashSet<region::Scope>,
-}
-
-struct DeleteTrivialEndRegions<'a> {
-    seen_regions: &'a FxHashSet<region::Scope>,
-}
-
-impl MirPass for CleanEndRegions {
-    fn run_pass<'a, 'tcx>(&self,
-                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          _source: MirSource,
-                          mir: &mut Mir<'tcx>) {
-        if !tcx.emit_end_regions() { return; }
-
-        let mut gather = GatherBorrowedRegions::default();
-        gather.visit_mir(mir);
-
-        let mut delete = DeleteTrivialEndRegions { seen_regions: &mut gather.seen_regions };
-        delete.visit_mir(mir);
-    }
-}
-
-impl<'tcx> Visitor<'tcx> for GatherBorrowedRegions {
-    fn visit_rvalue(&mut self,
-                    rvalue: &Rvalue<'tcx>,
-                    location: Location) {
-        // Gather regions that are used for borrows
-        if let Rvalue::Ref(r, _, _) = *rvalue {
-            if let RegionKind::ReScope(ce) = *r {
-                self.seen_regions.insert(ce);
-            }
-        }
-        self.super_rvalue(rvalue, location);
-    }
-
-    fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
-        // Gather regions that occur in types
-        let mut regions = smallvec![];
-        for t in ty.walk() {
-            t.push_regions(&mut regions);
-        }
-        for re in regions {
-            match *re {
-                RegionKind::ReScope(ce) => { self.seen_regions.insert(ce); }
-                _ => {},
-            }
-        }
-        self.super_ty(ty);
-    }
-}
-
-impl<'a, 'tcx> MutVisitor<'tcx> for DeleteTrivialEndRegions<'a> {
-    fn visit_statement(&mut self,
-                       block: BasicBlock,
-                       statement: &mut Statement<'tcx>,
-                       location: Location) {
-        let mut delete_it = false;
-
-        if let StatementKind::EndRegion(ref region_scope) = statement.kind {
-            if !self.seen_regions.contains(region_scope) {
-                delete_it = true;
-            }
-        }
-
-        if delete_it {
-            statement.make_nop();
-        }
-        self.super_statement(block, statement, location);
-    }
-}
-
 pub struct CleanAscribeUserType;
 
 pub struct DeleteAscribeUserType;
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 6351a6b40cb..a5b5a7e86d2 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -12,7 +12,7 @@
 //! We want to do this once just before codegen, so codegen does not have to take
 //! care erasing regions all over the place.
 //! NOTE:  We do NOT erase regions of statements that are relevant for
-//! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid, and EndRegion.
+//! "types-as-contracts"-validation, namely, AcquireValid, ReleaseValid
 
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -54,10 +54,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
                        block: BasicBlock,
                        statement: &mut Statement<'tcx>,
                        location: Location) {
-        if let StatementKind::EndRegion(_) = statement.kind {
-            statement.kind = StatementKind::Nop;
-        }
-
         self.super_statement(block, statement, location);
     }
 }
diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs
index 8d3a04f9f3c..a77e9b502ac 100644
--- a/src/librustc_mir/transform/mod.rs
+++ b/src/librustc_mir/transform/mod.rs
@@ -209,9 +209,6 @@ fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Stea
 
     let mut mir = tcx.mir_built(def_id).steal();
     run_passes(tcx, &mut mir, def_id, MirPhase::Const, &[
-        // Remove all `EndRegion` statements that are not involved in borrows.
-        &cleanup_post_borrowck::CleanEndRegions,
-
         // What we need to do constant evaluation.
         &simplify::SimplifyCfg::new("initial"),
         &type_check::TypeckMir,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 00309b0a3e9..816e8594885 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1168,7 +1168,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                 StatementKind::StorageLive(_) |
                 StatementKind::StorageDead(_) |
                 StatementKind::InlineAsm {..} |
-                StatementKind::EndRegion(_) |
                 StatementKind::Retag { .. } |
                 StatementKind::EscapeToRaw { .. } |
                 StatementKind::AscribeUserType(..) |
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 958e5efe3ec..13e134ba859 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -243,7 +243,6 @@ fn check_statement(
         | StatementKind::StorageDead(_)
         | StatementKind::Retag { .. }
         | StatementKind::EscapeToRaw { .. }
-        | StatementKind::EndRegion(_)
         | StatementKind::AscribeUserType(..)
         | StatementKind::Nop => Ok(()),
     }
diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs
index 445ffbbcf34..a31d12baed2 100644
--- a/src/librustc_mir/transform/remove_noop_landing_pads.rs
+++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs
@@ -52,12 +52,9 @@ impl RemoveNoopLandingPads {
                 StatementKind::FakeRead(..) |
                 StatementKind::StorageLive(_) |
                 StatementKind::StorageDead(_) |
-                StatementKind::EndRegion(_) |
                 StatementKind::AscribeUserType(..) |
                 StatementKind::Nop => {
-                    // These are all nops in a landing pad (there's some
-                    // borrowck interaction between EndRegion and storage
-                    // instructions, but this should all run after borrowck).
+                    // These are all nops in a landing pad
                 }
 
                 StatementKind::Assign(Place::Local(_), box Rvalue::Use(_)) => {
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 8f026c706fd..f852195b835 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -161,7 +161,6 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             mir::StatementKind::StorageLive(_) |
             mir::StatementKind::StorageDead(_) |
             mir::StatementKind::InlineAsm { .. } |
-            mir::StatementKind::EndRegion(_) |
             mir::StatementKind::Retag { .. } |
             mir::StatementKind::EscapeToRaw { .. } |
             mir::StatementKind::AscribeUserType(..) |
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index 68840ed4a48..fb37f03a1cc 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -83,7 +83,6 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
         self.record(match statement.kind {
             StatementKind::Assign(..) => "StatementKind::Assign",
             StatementKind::FakeRead(..) => "StatementKind::FakeRead",
-            StatementKind::EndRegion(..) => "StatementKind::EndRegion",
             StatementKind::Retag { .. } => "StatementKind::Retag",
             StatementKind::EscapeToRaw { .. } => "StatementKind::EscapeToRaw",
             StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs
deleted file mode 100644
index dd1c2bd5126..00000000000
--- a/src/test/mir-opt/end_region_1.rs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z emit-end-regions
-// ignore-tidy-linelength
-
-// This is just about the simplest program that exhibits an EndRegion.
-
-fn main() {
-    let a = 3;
-    let b = &a;
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-//     let mut _0: ();
-//     ...
-//     let _2: &'11_1rs i32;
-//     ...
-//     let _1: i32;
-//     ...
-//     bb0: {
-//         StorageLive(_1);
-//         _1 = const 3i32;
-//         FakeRead(ForLet, _1);
-//         StorageLive(_2);
-//         _2 = &'11_1rs _1;
-//         FakeRead(ForLet, _2);
-//         _0 = ();
-//         EndRegion('11_1rs);
-//         StorageDead(_2);
-//         StorageDead(_1);
-//         return;
-//     }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs
deleted file mode 100644
index 6b0a28b8110..00000000000
--- a/src/test/mir-opt/end_region_2.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z emit-end-regions
-// ignore-tidy-linelength
-
-// We will EndRegion for borrows in a loop that occur before break but
-// not those after break.
-
-fn main() {
-    loop {
-        let a = true;
-        let b = &a;
-        if a { break; }
-        let c = &a;
-    }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-//     let mut _0: ();
-//     ...
-//     let _7: &'26_3rs bool;
-//     ...
-//     let _3: &'26_1rs bool;
-//     ...
-//     let _2: bool;
-//     ...
-//     let mut _4: ();
-//     let mut _5: bool;
-//     ...
-//     bb0: {
-//         goto -> bb1;
-//     }
-//     bb1: {
-//          falseUnwind -> [real: bb2, cleanup: bb3];
-//     }
-//     bb2: {
-//         StorageLive(_2);
-//         _2 = const true;
-//         FakeRead(ForLet, _2);
-//         StorageLive(_3);
-//         _3 = &'26_1rs _2;
-//         FakeRead(ForLet, _3);
-//         StorageLive(_5);
-//         _5 = _2;
-//         switchInt(move _5) -> [false: bb5, otherwise: bb4];
-//     }
-//     bb3: {
-//         ...
-//     }
-//     bb4: {
-//         _0 = ();
-//         StorageDead(_5);
-//         EndRegion('26_1rs);
-//         StorageDead(_3);
-//         StorageDead(_2);
-//         return;
-//     }
-//     bb5: {
-//         _4 = ();
-//         StorageDead(_5);
-//         StorageLive(_7);
-//         _7 = &'26_3rs _2;
-//         FakeRead(ForLet, _7);
-//         _1 = ();
-//         EndRegion('26_3rs);
-//         StorageDead(_7);
-//         EndRegion('26_1rs);
-//         StorageDead(_3);
-//         StorageDead(_2);
-//         goto -> bb1;
-//     }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs
deleted file mode 100644
index d8d48358e53..00000000000
--- a/src/test/mir-opt/end_region_3.rs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z emit-end-regions
-// ignore-tidy-linelength
-
-// Binding the borrow's subject outside the loop does not increase the
-// scope of the borrow.
-
-fn main() {
-    let mut a;
-    loop {
-        a = true;
-        let b = &a;
-        if a { break; }
-        let c = &a;
-    }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-//     let mut _0: ();
-//     ...
-//     let _7: &'30_3rs bool;
-//     ...
-//     let _3: &'30_1rs bool;
-//     ...
-//     let mut _1: bool;
-//     ...
-//     let mut _2: ();
-//     let mut _4: ();
-//     let mut _5: bool;
-//     let mut _6: !;
-//     bb0: {
-//         StorageLive(_1);
-//         goto -> bb1;
-//     }
-//     bb1: {
-//         falseUnwind -> [real: bb2, cleanup: bb3];
-//     }
-//     bb2: {
-//         _1 = const true;
-//         StorageLive(_3);
-//         _3 = &'30_1rs _1;
-//         FakeRead(ForLet, _3);
-//         StorageLive(_5);
-//         _5 = _1;
-//         switchInt(move _5) -> [false: bb5, otherwise: bb4];
-//     }
-//     bb3: {
-//         ...
-//     }
-//     bb4: {
-//         _0 = ();
-//         StorageDead(_5);
-//         EndRegion('30_1rs);
-//         StorageDead(_3);
-//         StorageDead(_1);
-//         return;
-//     }
-//     bb5: {
-//         _4 = ();
-//         StorageDead(_5);
-//         StorageLive(_7);
-//         _7 = &'30_3rs _1;
-//         FakeRead(ForLet, _7);
-//         _2 = ();
-//         EndRegion('30_3rs);
-//         StorageDead(_7);
-//         EndRegion('30_1rs);
-//         StorageDead(_3);
-//         goto -> bb1;
-//     }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs
deleted file mode 100644
index 3d15f20bd05..00000000000
--- a/src/test/mir-opt/end_region_4.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z emit-end-regions
-// ignore-tidy-linelength
-
-// Unwinding should EndRegion for in-scope borrows: Direct borrows.
-
-fn main() {
-    let d = D(0);
-    let a = 0;
-    let b = &a;
-    foo(*b);
-    let c = &a;
-}
-
-struct D(i32);
-impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
-
-fn foo(i: i32) {
-    if i > 0 { panic!("im positive"); }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-//     let mut _0: ();
-//     ...
-//     let _6: &'31_4rs i32;
-//     ...
-//     let _3: &'31_2rs i32;
-//     ...
-//     let _2: i32;
-//     ...
-//     let _1: D;
-//     ...
-//     let mut _4: ();
-//     let mut _5: i32;
-//     bb0: {
-//         StorageLive(_1);
-//         _1 = D(const 0i32,);
-//         FakeRead(ForLet, _1);
-//         StorageLive(_2);
-//         _2 = const 0i32;
-//         FakeRead(ForLet, _2);
-//         StorageLive(_3);
-//         _3 = &'31_2rs _2;
-//         FakeRead(ForLet, _3);
-//         StorageLive(_5);
-//         _5 = (*_3);
-//         _4 = const foo(move _5) -> [return: bb2, unwind: bb3];
-//     }
-//     bb1: {
-//         resume;
-//     }
-//     bb2: {
-//         StorageDead(_5);
-//         StorageLive(_6);
-//         _6 = &'31_4rs _2;
-//         FakeRead(ForLet, _6);
-//         _0 = ();
-//         EndRegion('31_4rs);
-//         StorageDead(_6);
-//         EndRegion('31_2rs);
-//         StorageDead(_3);
-//         StorageDead(_2);
-//         drop(_1) -> [return: bb4, unwind: bb1];
-//     }
-//     bb3: {
-//         EndRegion('31_2rs);
-//         drop(_1) -> bb1;
-//     }
-//     bb4: {
-//         StorageDead(_1);
-//         return;
-//     }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs
deleted file mode 100644
index 06d1fbabe16..00000000000
--- a/src/test/mir-opt/end_region_5.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-
-// Unwinding should EndRegion for in-scope borrows: Borrowing via by-ref closure.
-
-fn main() {
-    let d = D(0);
-    foo(|| -> i32 { d.0 });
-}
-
-struct D(i32);
-impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
-
-fn foo<F>(f: F) where F: FnOnce() -> i32 {
-    if f() > 0 { panic!("im positive"); }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-// fn main() -> () {
-//     ...
-//     let mut _0: ();
-//     ...
-//     let _1: D;
-//     ...
-//     let mut _2: ();
-//     let mut _3: [closure@NodeId(28) d:&'18s D];
-//     let mut _4: &'18s D;
-//     bb0: {
-//         StorageLive(_1);
-//         _1 = D(const 0i32,);
-//         FakeRead(ForLet, _1);
-//         StorageLive(_3);
-//         StorageLive(_4);
-//         _4 = &'18s _1;
-//         _3 = [closure@NodeId(28)] { d: move _4 };
-//         StorageDead(_4);
-//         _2 = const foo(move _3) -> [return: bb2, unwind: bb3];
-//     }
-//     bb1: {
-//         resume;
-//     }
-//     bb2: {
-//         EndRegion('18s);
-//         StorageDead(_3);
-//         _0 = ();
-//         drop(_1) -> [return: bb4, unwind: bb1];
-//     }
-//     bb3: {
-//         EndRegion('18s);
-//         drop(_1) -> bb1;
-//     }
-//     bb4: {
-//         StorageDead(_1);
-//         return;
-//     }
-// }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
-
-// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
-// fn main::{{closure}}(_1: [closure@NodeId(28) d:&'18s D]) -> i32 {
-//    let mut _0: i32;
-//
-//    bb0: {
-//        _0 = ((*(_1.0: &'18s D)).0: i32);
-//        return;
-//    }
-// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs
deleted file mode 100644
index d0db23e6de0..00000000000
--- a/src/test/mir-opt/end_region_6.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-// ignore-tidy-linelength
-
-// Unwinding should EndRegion for in-scope borrows: 2nd borrow within by-ref closure.
-
-fn main() {
-    let d = D(0);
-    foo(|| -> i32 { let r = &d; r.0 });
-}
-
-struct D(i32);
-impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
-
-fn foo<F>(f: F) where F: FnOnce() -> i32 {
-    if f() > 0 { panic!("im positive"); }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-// fn main() -> () {
-//     let mut _0: ();
-//     ...
-//     let _1: D;
-//     ...
-//     let mut _2: ();
-//     let mut _3: [closure@NodeId(33) d:&'24s D];
-//     let mut _4: &'24s D;
-//     bb0: {
-//         StorageLive(_1);
-//         _1 = D(const 0i32,);
-//         FakeRead(ForLet, _1);
-//         StorageLive(_3);
-//         StorageLive(_4);
-//         _4 = &'24s _1;
-//         _3 = [closure@NodeId(33)] { d: move _4 };
-//         StorageDead(_4);
-//         _2 = const foo(move _3) -> [return: bb2, unwind: bb3];
-//     }
-//     bb1: {
-//         resume;
-//     }
-//     bb2: {
-//         EndRegion('24s);
-//         StorageDead(_3);
-//         _0 = ();
-//         drop(_1) -> [return: bb4, unwind: bb1];
-//     }
-//     bb3: {
-//         EndRegion('24s);
-//         drop(_1) -> bb1;
-//     }
-//     bb4: {
-//         StorageDead(_1);
-//         return;
-//     }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
-
-// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
-// fn main::{{closure}}(_1: [closure@NodeId(33) d:&'24s D]) -> i32 {
-//     let mut _0: i32;
-//     ...
-//     let _2: &'21_0rs D;
-//     ...
-//     bb0: {
-//         StorageLive(_2);
-//         _2 = &'21_0rs (*(_1.0: &'24s D));
-//         FakeRead(ForLet, _2);
-//         _0 = ((*_2).0: i32);
-//         EndRegion('21_0rs);
-//         StorageDead(_2);
-//         return;
-//     }
-// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs
deleted file mode 100644
index c7df440ebe2..00000000000
--- a/src/test/mir-opt/end_region_7.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-// ignore-tidy-linelength
-
-// Unwinding should EndRegion for in-scope borrows: Borrow of moved data.
-
-fn main() {
-    let d = D(0);
-    foo(move || -> i32 { let r = &d; r.0 });
-}
-
-struct D(i32);
-impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
-
-fn foo<F>(f: F) where F: FnOnce() -> i32 {
-    if f() > 0 { panic!("im positive"); }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-// fn main() -> () {
-//     let mut _0: ();
-//     ...
-//     let _1: D;
-//     ...
-//     let mut _2: ();
-//     let mut _3: [closure@NodeId(33) d:D];
-//     bb0: {
-//         StorageLive(_1);
-//         _1 = D(const 0i32,);
-//         FakeRead(ForLet, _1);
-//         StorageLive(_3);
-//         _3 = [closure@NodeId(33)] { d: move _1 };
-//         _2 = const foo(move _3) -> [return: bb2, unwind: bb4];
-//     }
-//     bb1: {
-//         resume;
-//     }
-//     bb2: {
-//         drop(_3) -> [return: bb5, unwind: bb3];
-//     }
-//     bb3: {
-//         drop(_1) -> bb1;
-//     }
-//     bb4: {
-//         drop(_3) -> bb3;
-//     }
-//     bb5: {
-//         StorageDead(_3);
-//         _0 = ();
-//         drop(_1) -> [return: bb6, unwind: bb1];
-//     }
-//     bb6: {
-//         StorageDead(_1);
-//         return;
-//     }
-// }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
-
-// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
-// fn main::{{closure}}(_1: [closure@NodeId(33) d:D]) -> i32 {
-//     let mut _0: i32;
-//     ...
-//     let _2: &'21_0rs D;
-//     ...
-//     bb0: {
-//         StorageLive(_2);
-//         _2 = &'21_0rs (_1.0: D);
-//         FakeRead(ForLet, _2);
-//         _0 = ((*_2).0: i32);
-//         EndRegion('21_0rs);
-//         StorageDead(_2);
-//         drop(_1) -> [return: bb2, unwind: bb1];
-//     }
-//     bb1: {
-//         resume;
-//     }
-//     bb2: {
-//         return;
-//     }
-// }
-// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs
deleted file mode 100644
index 9f2a9c3b72e..00000000000
--- a/src/test/mir-opt/end_region_8.rs
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-// ignore-tidy-linelength
-
-// Unwinding should EndRegion for in-scope borrows: Move of borrow into closure.
-
-fn main() {
-    let d = D(0);
-    let r = &d;
-    foo(move || -> i32 { r.0 });
-}
-
-struct D(i32);
-impl Drop for D { fn drop(&mut self) { println!("dropping D({})", self.0); } }
-
-fn foo<F>(f: F) where F: FnOnce() -> i32 {
-    if f() > 0 { panic!("im positive"); }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-// fn main() -> () {
-//    let mut _0: ();
-//    ...
-//    let _2: &'26_1rs D;
-//    ...
-//    let _1: D;
-//    ...
-//    let mut _3: ();
-//    let mut _4: [closure@NodeId(33) r:&'24s D];
-//    bb0: {
-//        StorageLive(_1);
-//        _1 = D(const 0i32,);
-//        FakeRead(ForLet, _1);
-//        StorageLive(_2);
-//        _2 = &'26_1rs _1;
-//        FakeRead(ForLet, _2);
-//        StorageLive(_4);
-//        _4 = [closure@NodeId(33)] { r: _2 };
-//        _3 = const foo(move _4) -> [return: bb2, unwind: bb3];
-//    }
-//    bb1: {
-//        resume;
-//    }
-//    bb2: {
-//        EndRegion('24s);
-//        StorageDead(_4);
-//        _0 = ();
-//        EndRegion('26_1rs);
-//        StorageDead(_2);
-//        drop(_1) -> [return: bb4, unwind: bb1];
-//    }
-//    bb3: {
-//        EndRegion('24s);
-//        EndRegion('26_1rs);
-//        drop(_1) -> bb1;
-//    }
-//    bb4: {
-//        StorageDead(_1);
-//        return;
-//    }
-// }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
-
-// START rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
-// fn main::{{closure}}(_1: [closure@NodeId(33) r:&'24s D]) -> i32 {
-//     let mut _0: i32;
-//
-//     bb0: {
-//         _0 = ((*(_1.0: &'26_1rs D)).0: i32);
-//         return;
-//     }
-// }
-// END rustc.main-{{closure}}.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs
deleted file mode 100644
index ef2d949d307..00000000000
--- a/src/test/mir-opt/end_region_9.rs
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-// ignore-tidy-linelength
-
-// This test models a scenario that arielb1 found during review.
-// Namely, any filtering of EndRegions must ensure to continue to emit
-// any necessary EndRegions that occur earlier in the source than the
-// first borrow involving that region.
-//
-// It is tricky to actually construct examples of this, which is the
-// main reason that I am keeping this test even though I have now
-// removed the pre-filter that motivated the test in the first place.
-
-fn main() {
-    let mut second_iter = false;
-    let x = 3;
-    'a: loop {
-        let mut y;
-        loop {
-            if second_iter {
-                break 'a; // want to generate `EndRegion('a)` here
-            } else {
-                y = &/*'a*/ x;
-            }
-            second_iter = true;
-        }
-    }
-}
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-// fn main() -> () {
-//     let mut _0: ();
-//     ...
-//     let mut _4: &'37_0rs i32;
-//     ...
-//     let _2: i32;
-//     ...
-//     let mut _1: bool;
-//     ...
-//     let mut _3: ();
-//     let mut _5: !;
-//     let mut _6: ();
-//     let mut _7: bool;
-//     let mut _8: !;
-//     bb0: {
-//        StorageLive(_1);
-//        _1 = const false;
-//        FakeRead(ForLet, _1);
-//        StorageLive(_2);
-//        _2 = const 3i32;
-//        FakeRead(ForLet, _2);
-//        falseUnwind -> [real: bb2, cleanup: bb1];
-//    }
-//    bb1: {
-//        ...
-//    }
-//    bb2: {
-//        StorageLive(_4);
-//        goto -> bb3;
-//    }
-//    bb3: {
-//        falseUnwind -> [real: bb4, cleanup: bb1];
-//    }
-//    bb4: {
-//        StorageLive(_7);
-//        _7 = _1;
-//        switchInt(move _7) -> [false: bb6, otherwise: bb5];
-//    }
-//    bb5: {
-//        _0 = ();
-//        StorageDead(_7);
-//        EndRegion('37_0rs);
-//        StorageDead(_4);
-//        StorageDead(_2);
-//        StorageDead(_1);
-//        return;
-//    }
-//    bb6: {
-//        _4 = &'37_0rs _2;
-//        _6 = ();
-//        StorageDead(_7);
-//        _1 = const true;
-//        _3 = ();
-//        goto -> bb3;
-//    }
-// }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs
deleted file mode 100644
index 3dbc73caf65..00000000000
--- a/src/test/mir-opt/end_region_cyclic.rs
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-// ignore-tidy-linelength
-
-// This test models a scenario with a cyclic reference. Rust obviously
-// needs to handle such cases.
-//
-// The interesting part about this test is that such case shows that
-// one cannot generally force all references to be dead before you hit
-// their EndRegion; at least, not without breaking the more important
-// property that all borrowed storage locations have their regions
-// ended strictly before their StorageDeads. (This test was inspired
-// by discussion on Issue #43481.)
-
-use std::cell::Cell;
-
-struct S<'a> {
-    r: Cell<Option<&'a S<'a>>>,
-}
-
-fn main() {
-    loop {
-        let x = S { r: Cell::new(None) };
-        x.r.set(Some(&x));
-        if query() { break; }
-        x.r.set(Some(&x));
-    }
-}
-
-fn query() -> bool { true }
-
-// END RUST SOURCE
-// START rustc.main.SimplifyCfg-qualify-consts.after.mir
-// fn main() -> (){
-//     let mut _0: ();
-//     scope 1 {
-//     }
-//     scope 2 {
-//         let _2: S<'49_0rs>;
-//     }
-//     let mut _1: ();
-//     let mut _3: std::cell::Cell<std::option::Option<&'49_0rs S<'49_0rs>>>;
-//     let mut _4: std::option::Option<&'49_0rs S<'49_0rs>>;
-//     let mut _5: ();
-//     let mut _6: &'25s std::cell::Cell<std::option::Option<&'49_0rs S<'49_0rs>>>;
-//     let mut _7: std::option::Option<&'49_0rs S<'49_0rs>>;
-//     let mut _8: &'49_0rs S<'49_0rs>;
-//     let mut _9: &'49_0rs S<'49_0rs>;
-//     let mut _10: ();
-//     let mut _11: bool;
-//     let mut _12: !;
-//     let mut _13: ();
-//     let mut _14: &'47s std::cell::Cell<std::option::Option<&'49_0rs S<'49_0rs>>>;
-//     let mut _15: std::option::Option<&'49_0rs S<'49_0rs>>;
-//     let mut _16: &'49_0rs S<'49_0rs>;
-//     let mut _17: &'49_0rs S<'49_0rs>;
-//     bb0: {
-//         goto -> bb1;
-//     }
-//     bb1: {
-//         falseUnwind -> [real: bb2, cleanup: bb3];
-//     }
-//     bb2: {
-//         StorageLive(_2);
-//         StorageLive(_3);
-//         StorageLive(_4);
-//         _4 = std::option::Option<&'49_0rs S<'49_0rs>>::None;
-//         _3 = const <std::cell::Cell<T>>::new(move _4) -> [return: bb4, unwind: bb3];
-//     }
-//     bb3: {
-//         resume;
-//     }
-//     bb4: {
-//         StorageDead(_4);
-//         _2 = S<'49_0rs> { r: move _3 };
-//         StorageDead(_3);
-//         FakeRead(ForLet, _2);
-//         StorageLive(_6);
-//         _6 = &'25s (_2.0: std::cell::Cell<std::option::Option<&'49_0rs S<'49_0rs>>>);
-//         StorageLive(_7);
-//         StorageLive(_8);
-//         StorageLive(_9);
-//         _9 = &'49_0rs _2;
-//         _8 = &'49_0rs (*_9);
-//         _7 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _8,);
-//         StorageDead(_8);
-//         _5 = const <std::cell::Cell<T>>::set(move _6, move _7) -> [return: bb5, unwind: bb3];
-//     }
-//     bb5: {
-//         EndRegion('25s);
-//         StorageDead(_7);
-//         StorageDead(_6);
-//         StorageDead(_9);
-//         StorageLive(_11);
-//         _11 = const query() -> [return: bb6, unwind: bb3];
-//     }
-//     bb6: {
-//         switchInt(move _11) -> [false: bb8, otherwise: bb7];
-//     }
-//     bb7: {
-//         _0 = ();
-//         StorageDead(_11);
-//         EndRegion('49_0rs);
-//         StorageDead(_2);
-//         return;
-//     }
-//     bb8: {
-//         _10 = ();
-//         StorageDead(_11);
-//         StorageLive(_14);
-//         _14 = &'47s (_2.0: std::cell::Cell<std::option::Option<&'49_0rs S<'49_0rs>>>);
-//         StorageLive(_15);
-//         StorageLive(_16);
-//         StorageLive(_17);
-//         _17 = &'49_0rs _2;
-//         _16 = &'49_0rs (*_17);
-//         _15 = std::option::Option<&'49_0rs S<'49_0rs>>::Some(move _16,);
-//         StorageDead(_16);
-//         _13 = const <std::cell::Cell<T>>::set(move _14, move _15) -> [return: bb9, unwind: bb3];
-//     }
-//     bb9: {
-//         EndRegion('47s);
-//         StorageDead(_15);
-//         StorageDead(_14);
-//         StorageDead(_17);
-//         _1 = ();
-//         EndRegion('49_0rs);
-//         StorageDead(_2);
-//         goto -> bb1;
-//     }
-// }
-// END rustc.main.SimplifyCfg-qualify-consts.after.mir
diff --git a/src/test/mir-opt/end_region_destruction_extents_1.rs b/src/test/mir-opt/end_region_destruction_extents_1.rs
deleted file mode 100644
index eb381dfc552..00000000000
--- a/src/test/mir-opt/end_region_destruction_extents_1.rs
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-// ignore-tidy-linelength
-
-// A scenario with significant destruction code extents (which have
-// suffix "dce" in current `-Z identify_regions` rendering).
-
-#![feature(dropck_eyepatch)]
-
-fn main() {
-    // Since the second param to `D1` is may_dangle, it is legal for
-    // the region of that parameter to end before the drop code for D1
-    // is executed.
-    (D1(&S1("ex1"), &S1("dang1"))).0;
-}
-
-#[derive(Debug)]
-struct S1(&'static str);
-
-#[derive(Debug)]
-struct D1<'a, 'b>(&'a S1, &'b S1);
-
-// The `#[may_dangle]` means that references of type `&'b _` may be
-// invalid during the execution of this destructor; i.e. in this case
-// the destructor code is not allowed to read or write `*self.1`, while
-// it can read/write `*self.0`.
-unsafe impl<'a, #[may_dangle] 'b> Drop for D1<'a, 'b> {
-    fn drop(&mut self) {
-        println!("D1({:?}, _)", self.0);
-    }
-}
-
-// Notes on the MIR output below:
-//
-// 1. The `EndRegion('13s)` is allowed to precede the `drop(_3)`
-//    solely because of the #[may_dangle] mentioned above.
-//
-// 2. Regarding the occurrence of `EndRegion('15ds)` *after* `StorageDead(_6)`
-//    (where we have borrows `&'15ds _6`): Eventually:
-//
-//    i. this code should be rejected (by mir-borrowck), or
-//
-//    ii. the MIR code generation should be changed so that the
-//        EndRegion('15ds)` precedes `StorageDead(_6)` in the
-//        control-flow.  (Note: arielb1 views drop+storagedead as one
-//        unit, and does not see this option as a useful avenue to
-//        explore.), or
-//
-//    iii. the presence of EndRegion should be made irrelevant by a
-//        transformation encoding the effects of rvalue-promotion.
-//        This may be the simplest and most-likely option; note in
-//        particular that `StorageDead(_6)` goes away below in
-//        rustc.main.QualifyAndPromoteConstants.after.mir
-
-// END RUST SOURCE
-
-// START rustc.main.QualifyAndPromoteConstants.before.mir
-// fn main() -> () {
-// let mut _0: ();
-//     let mut _1: &'15ds S1;
-//     let mut _2: D1<'15ds, '13s>;
-//     let mut _3: &'15ds S1;
-//     let mut _4: &'15ds S1;
-//     let _5: S1;
-//     let mut _6: &'13s S1;
-//     let mut _7: &'13s S1;
-//     let _8: S1;
-//     bb0: {
-//         StorageLive(_2);
-//         StorageLive(_3);
-//         StorageLive(_4);
-//         StorageLive(_5);
-//         _5 = S1(const "ex1",);
-//         _4 = &'15ds _5;
-//         _3 = &'15ds (*_4);
-//         StorageLive(_6);
-//         StorageLive(_7);
-//         StorageLive(_8);
-//         _8 = S1(const "dang1",);
-//         _7 = &'13s _8;
-//         _6 = &'13s (*_7);
-//         _2 = D1<'15ds, '13s>(move _3, move _6);
-//         EndRegion('13s);
-//         StorageDead(_6);
-//         StorageDead(_3);
-//         _1 = (_2.0: &'15ds S1);
-//         drop(_2) -> [return: bb2, unwind: bb1];
-//     }
-//     bb1: {
-//         resume;
-//     }
-//     bb2: {
-//         StorageDead(_2);
-//         StorageDead(_7);
-//         StorageDead(_8);
-//         StorageDead(_4);
-//         StorageDead(_5);
-//         EndRegion('15ds);
-//         _0 = ();
-//         return;
-//     }
-// }
-// END rustc.main.QualifyAndPromoteConstants.before.mir
-
-// START rustc.main.QualifyAndPromoteConstants.after.mir
-// fn main() -> (){
-//     let mut _0: ();
-//     let mut _1: &'15ds S1;
-//     let mut _2: D1<'15ds, '13s>;
-//     let mut _3: &'15ds S1;
-//     let mut _4: &'15ds S1;
-//     let _5: S1;
-//     let mut _6: &'13s S1;
-//     let mut _7: &'13s S1;
-//     let _8: S1;
-//     bb0: {
-//         StorageLive(_2);
-//         StorageLive(_3);
-//         StorageLive(_4);
-//         _4 = &'15ds (promoted[1]: S1);
-//         _3 = &'15ds (*_4);
-//         StorageLive(_6);
-//         StorageLive(_7);
-//         _7 = &'13s (promoted[0]: S1);
-//         _6 = &'13s (*_7);
-//         _2 = D1<'15ds, '13s>(move _3, move _6);
-//         EndRegion('13s);
-//         StorageDead(_6);
-//         StorageDead(_3);
-//         _1 = (_2.0: &'15ds S1);
-//         drop(_2) -> [return: bb2, unwind: bb1];
-//     }
-//     bb1: {
-//         resume;
-//     }
-//     bb2: {
-//         StorageDead(_2);
-//         StorageDead(_7);
-//         StorageDead(_4);
-//         EndRegion('15ds);
-//         _0 = ();
-//         return;
-//     }
-// }
-// END rustc.main.QualifyAndPromoteConstants.after.mir
diff --git a/src/test/mir-opt/issue-43457.rs b/src/test/mir-opt/issue-43457.rs
deleted file mode 100644
index 85cecc5070c..00000000000
--- a/src/test/mir-opt/issue-43457.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z identify_regions -Z span_free_formats -Z emit-end-regions
-// ignore-tidy-linelength
-
-// Regression test for #43457: an `EndRegion` was missing from output
-// because compiler was using a faulty means for region map lookup.
-
-use std::cell::RefCell;
-
-fn rc_refcell_test(r: RefCell<i32>) {
-    r.borrow_mut();
-}
-
-fn main() { }
-
-// END RUST SOURCE
-// START rustc.rc_refcell_test.SimplifyCfg-qualify-consts.after.mir
-//
-// fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () {
-//     let mut _0: ();
-//     scope 1 {
-//         let _2: std::cell::RefCell<i32>;
-//     }
-//     let mut _3: std::cell::RefMut<'17ds, i32>;
-//     let mut _4: &'17ds std::cell::RefCell<i32>;
-//
-//     bb0: {
-//         StorageLive(_2);
-//         _2 = _1;
-//         StorageLive(_4);
-//         _4 = &'17ds _2;
-//         _3 = const <std::cell::RefCell<T>>::borrow_mut(_4) -> bb1;
-//     }
-//
-//     bb1: {
-//         drop(_3) -> bb2;
-//     }
-//
-//     bb2: {
-//         StorageDead(_4);
-//         EndRegion('17ds);
-//         _0 = ();
-//         StorageDead(_2);
-//         return;
-//     }
-// }
diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs
index f9024b67063..d8365c8c9cc 100644
--- a/src/test/mir-opt/issue-49232.rs
+++ b/src/test/mir-opt/issue-49232.rs
@@ -44,7 +44,7 @@ fn main() {
 //         falseUnwind -> [real: bb3, cleanup: bb4];
 //     }
 //     bb2: {
-//         goto -> bb29;
+//         goto -> bb20;
 //     }
 //     bb3: {
 //         StorageLive(_2);
@@ -90,58 +90,31 @@ fn main() {
 //         StorageDead(_3);
 //         StorageLive(_6);
 //         _6 = &_2;
-//         _5 = const std::mem::drop(move _6) -> [return: bb28, unwind: bb4];
+//         _5 = const std::mem::drop(move _6) -> [return: bb19, unwind: bb4];
 //     }
 //     bb15: {
+//         StorageDead(_3);
 //         goto -> bb16;
 //     }
 //     bb16: {
-//         goto -> bb17;
-//     }
-//     bb17: {
-//         goto -> bb18;
-//     }
-//     bb18: {
-//         goto -> bb19;
-//     }
-//     bb19: {
-//         goto -> bb20;
-//     }
-//     bb20: {
-//         StorageDead(_3);
-//         goto -> bb21;
-//     }
-//     bb21: {
-//         goto -> bb22;
-//     }
-//     bb22: {
 //         StorageDead(_2);
-//         goto -> bb23;
-//     }
-//     bb23: {
-//         goto -> bb24;
-//     }
-//     bb24: {
-//         goto -> bb25;
-//     }
-//     bb25: {
 //         goto -> bb2;
 //     }
-//     bb26: {
+//     bb17: {
 //         _4 = ();
 //         unreachable;
 //     }
-//     bb27: {
+//     bb18: {
 //         StorageDead(_4);
 //         goto -> bb14;
 //     }
-//     bb28: {
+//     bb19: {
 //         StorageDead(_6);
 //         _1 = ();
 //         StorageDead(_2);
 //         goto -> bb1;
 //     }
-//     bb29: {
+//     bb20: {
 //         return;
 //     }
 // }
diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs
index 2e526a221cc..77616f1d39a 100644
--- a/src/test/mir-opt/loop_test.rs
+++ b/src/test/mir-opt/loop_test.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z identify_regions -Z emit-end-regions
+// compile-flags: -Z identify_regions
 
 // Tests to make sure we correctly generate falseUnwind edges in loops
 
diff --git a/src/test/run-pass/issues/issue-16671.rs b/src/test/run-pass/issues/issue-16671.rs
index 5ff2bc97ae2..14bda56dd8f 100644
--- a/src/test/run-pass/issues/issue-16671.rs
+++ b/src/test/run-pass/issues/issue-16671.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // run-pass
-//compile-flags: -Z borrowck=compare -Z emit-end-regions
+//compile-flags: -Z borrowck=compare
 
 #![deny(warnings)]
 
diff --git a/src/test/ui/borrowck/immutable-arg.rs b/src/test/ui/borrowck/immutable-arg.rs
index 7c387ed0808..c5291ab3e1d 100644
--- a/src/test/ui/borrowck/immutable-arg.rs
+++ b/src/test/ui/borrowck/immutable-arg.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Z borrowck=compare
+//compile-flags: -Z borrowck=compare
 
 fn foo(_x: u32) {
     _x = 4;
diff --git a/src/test/ui/issues/issue-45697-1.rs b/src/test/ui/issues/issue-45697-1.rs
index b8be209833a..e79bfb23b05 100644
--- a/src/test/ui/issues/issue-45697-1.rs
+++ b/src/test/ui/issues/issue-45697-1.rs
@@ -11,7 +11,7 @@
 // Test that assignments to an `&mut` pointer which is found in a
 // borrowed (but otherwise non-aliasable) location is illegal.
 
-// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=on
+// compile-flags: -Z borrowck=compare -C overflow-checks=on
 
 struct S<'a> {
     pointer: &'a mut isize
diff --git a/src/test/ui/issues/issue-45697.rs b/src/test/ui/issues/issue-45697.rs
index 27acc2c89f7..936e8a40fa8 100644
--- a/src/test/ui/issues/issue-45697.rs
+++ b/src/test/ui/issues/issue-45697.rs
@@ -11,7 +11,7 @@
 // Test that assignments to an `&mut` pointer which is found in a
 // borrowed (but otherwise non-aliasable) location is illegal.
 
-// compile-flags: -Z emit-end-regions -Z borrowck=compare -C overflow-checks=off
+// compile-flags: -Z borrowck=compare -C overflow-checks=off
 
 struct S<'a> {
     pointer: &'a mut isize
diff --git a/src/test/ui/issues/issue-46023.rs b/src/test/ui/issues/issue-46023.rs
index d5c8cd6d0f8..ea7e627eadf 100644
--- a/src/test/ui/issues/issue-46023.rs
+++ b/src/test/ui/issues/issue-46023.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 // revisions: ast mir
-//[mir]compile-flags: -Z emit-end-regions -Z borrowck=mir
+//[mir]compile-flags: -Z borrowck=mir
 
 fn main() {
     let x = 0;
diff --git a/src/test/ui/issues/issue-46471-1.rs b/src/test/ui/issues/issue-46471-1.rs
index 0dbcdea89f9..7fb77f9ce8b 100644
--- a/src/test/ui/issues/issue-46471-1.rs
+++ b/src/test/ui/issues/issue-46471-1.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z emit-end-regions -Z borrowck=compare
+// compile-flags: -Z borrowck=compare
 
 fn main() {
     let y = {
diff --git a/src/test/ui/issues/issue-46471.rs b/src/test/ui/issues/issue-46471.rs
index 654a3d8f964..201b8e2de9a 100644
--- a/src/test/ui/issues/issue-46471.rs
+++ b/src/test/ui/issues/issue-46471.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z emit-end-regions -Z borrowck=compare
+// compile-flags: -Z borrowck=compare
 
 fn foo() -> &'static u32 {
     let x = 0;
diff --git a/src/test/ui/issues/issue-46472.rs b/src/test/ui/issues/issue-46472.rs
index 8137cd2dd89..b6838a48b1b 100644
--- a/src/test/ui/issues/issue-46472.rs
+++ b/src/test/ui/issues/issue-46472.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z emit-end-regions -Z borrowck=compare
+// compile-flags: -Z borrowck=compare
 
 fn bar<'a>() -> &'a mut u32 {
     &mut 4
diff --git a/src/test/ui/moves/moves-based-on-type-tuple.rs b/src/test/ui/moves/moves-based-on-type-tuple.rs
index 27903fee117..9dda275d95e 100644
--- a/src/test/ui/moves/moves-based-on-type-tuple.rs
+++ b/src/test/ui/moves/moves-based-on-type-tuple.rs
@@ -10,7 +10,7 @@
 
 #![feature(box_syntax)]
 
-// compile-flags: -Z emit-end-regions -Z borrowck=compare
+// compile-flags: -Z borrowck=compare
 
 fn dup(x: Box<isize>) -> Box<(Box<isize>,Box<isize>)> {
     box (x, x)
diff --git a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
index ae815a5efe9..f96e73ce09f 100644
--- a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags: -Z emit-end-regions -Zborrowck=mir
+// compile-flags: -Zborrowck=mir
 // compile-pass
 
 #![allow(warnings)]
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
index 00d146e0f02..0e9cdf2f428 100644
--- a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir
+//compile-flags: -Zborrowck=mir
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
index cd46014a7f5..080fdfe0228 100644
--- a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
+++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir
+//compile-flags: -Zborrowck=mir
 
 #![allow(warnings)]
 
diff --git a/src/test/ui/nll/maybe-initialized-drop.rs b/src/test/ui/nll/maybe-initialized-drop.rs
index 9a3aca34620..db680ef8bea 100644
--- a/src/test/ui/nll/maybe-initialized-drop.rs
+++ b/src/test/ui/nll/maybe-initialized-drop.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//compile-flags: -Z emit-end-regions -Zborrowck=mir
+//compile-flags: -Zborrowck=mir
 
 #![allow(warnings)]