Skip to content

Commit

Permalink
Add post-pass to remove EndRegions of unborrowed extents.
Browse files Browse the repository at this point in the history
  • Loading branch information
pnkfelix committed Jun 12, 2017
1 parent 1d315cf commit 0a5211e
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/librustc_driver/driver.rs
Expand Up @@ -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);
Expand Down
84 changes: 84 additions & 0 deletions 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 <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.

//! 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<CodeExtent>,
}

struct DeleteTrivialEndRegions<'a> {
seen_regions: &'a FxHashSet<CodeExtent>,
}

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);
}
}
1 change: 1 addition & 0 deletions src/librustc_mir/transform/mod.rs
Expand Up @@ -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;
Expand Down

0 comments on commit 0a5211e

Please sign in to comment.