From 0a5211e80951eeb89e6f8e9e10b31398904d8d76 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 22 May 2017 13:06:51 +0200 Subject: [PATCH] Add post-pass to remove EndRegions of unborrowed extents. --- src/librustc_driver/driver.rs | 3 + .../transform/clean_end_regions.rs | 84 +++++++++++++++++++ src/librustc_mir/transform/mod.rs | 1 + 3 files changed, 88 insertions(+) create mode 100644 src/librustc_mir/transform/clean_end_regions.rs diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index bca82ff9a46d..b1620ed53c71 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -912,6 +912,9 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut passes = Passes::new(); passes.push_hook(mir::transform::dump_mir::DumpMir); + // Remove all `EndRegion` statements that are not involved in borrows. + passes.push_pass(MIR_CONST, mir::transform::clean_end_regions::CleanEndRegions); + // What we need to do constant evaluation. passes.push_pass(MIR_CONST, mir::transform::simplify::SimplifyCfg::new("initial")); passes.push_pass(MIR_CONST, mir::transform::type_check::TypeckMir); diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs new file mode 100644 index 000000000000..36125f945436 --- /dev/null +++ b/src/librustc_mir/transform/clean_end_regions.rs @@ -0,0 +1,84 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! This module provides one pass, `CleanEndRegions`, that reduces the +//! set of `EndRegion` statements in the MIR. +//! +//! The "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. + +use rustc_data_structures::fx::FxHashSet; + +use rustc::middle::region::CodeExtent; +use rustc::mir::transform::{MirPass, MirSource}; +use rustc::mir::{BasicBlock, Location, Mir, Rvalue, Statement, StatementKind}; +use rustc::mir::visit::{MutVisitor, Visitor}; +use rustc::ty::{RegionKind, TyCtxt}; + +pub struct CleanEndRegions; + +struct GatherBorrowedRegions { + seen_regions: FxHashSet, +} + +struct DeleteTrivialEndRegions<'a> { + seen_regions: &'a FxHashSet, +} + +impl MirPass for CleanEndRegions { + fn run_pass<'a, 'tcx>(&self, + _tcx: TyCtxt<'a, 'tcx, 'tcx>, + _source: MirSource, + mir: &mut Mir<'tcx>) { + let mut gather = GatherBorrowedRegions { seen_regions: FxHashSet() }; + 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) { + if let Rvalue::Ref(r, _, _) = *rvalue { + if let RegionKind::ReScope(ce) = *r { + self.seen_regions.insert(ce); + } + } + self.super_rvalue(rvalue, location); + } +} + +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 extent) = statement.kind { + if !self.seen_regions.contains(extent) { + delete_it = true; + } + } + + if delete_it { + 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 fcea5d4c8604..4594c611d596 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -24,6 +24,7 @@ use syntax::ast; use syntax_pos::{DUMMY_SP, Span}; use transform; +pub mod clean_end_regions; pub mod simplify_branches; pub mod simplify; pub mod erase_regions;