Skip to content

Commit

Permalink
add a cache for MIR predecessors
Browse files Browse the repository at this point in the history
  • Loading branch information
arielb1 authored and Ariel Ben-Yehuda committed Jun 9, 2016
1 parent e3af9fa commit 6405527
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Expand Up @@ -102,6 +102,7 @@ pub mod middle {
}

pub mod mir {
mod cache;
pub mod repr;
pub mod tcx;
pub mod visit;
Expand Down
69 changes: 69 additions & 0 deletions src/librustc/mir/cache.rs
@@ -0,0 +1,69 @@
// Copyright 2016 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.

use std::cell::{Ref, RefCell};
use rustc_data_structures::indexed_vec::IndexVec;

use mir::repr::{Mir, BasicBlock};

use rustc_serialize as serialize;

#[derive(Clone)]
pub struct Cache {
predecessors: RefCell<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
}


impl serialize::Encodable for Cache {
fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
serialize::Encodable::encode(&(), s)
}
}

impl serialize::Decodable for Cache {
fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
serialize::Decodable::decode(d).map(|_v: ()| Self::new())
}
}


impl Cache {
pub fn new() -> Self {
Cache {
predecessors: RefCell::new(None)
}
}

pub fn invalidate(&self) {
// FIXME: consider being more fine-grained
*self.predecessors.borrow_mut() = None;
}

pub fn predecessors(&self, mir: &Mir) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> {
if self.predecessors.borrow().is_none() {
*self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
}

Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
}
}

fn calculate_predecessors(mir: &Mir) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
for (bb, data) in mir.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
for &tgt in term.successors().iter() {
result[tgt].push(bb);
}
}
}

result
}
20 changes: 19 additions & 1 deletion src/librustc/mir/repr.rs
Expand Up @@ -20,12 +20,15 @@ use rustc_back::slice;
use hir::InlineAsm;
use std::ascii;
use std::borrow::{Cow};
use std::cell::Ref;
use std::fmt::{self, Debug, Formatter, Write};
use std::{iter, u32};
use std::ops::{Index, IndexMut};
use syntax::ast::{self, Name};
use syntax::codemap::Span;

use super::cache::Cache;

macro_rules! newtype_index {
($name:ident, $debug_name:expr) => (
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
Expand Down Expand Up @@ -88,6 +91,9 @@ pub struct Mir<'tcx> {

/// A span representing this MIR, for error reporting
pub span: Span,

/// A cache for various calculations
cache: Cache
}

/// where execution begins
Expand All @@ -113,7 +119,8 @@ impl<'tcx> Mir<'tcx> {
arg_decls: arg_decls,
temp_decls: temp_decls,
upvar_decls: upvar_decls,
span: span
span: span,
cache: Cache::new()
}
}

Expand All @@ -124,8 +131,19 @@ impl<'tcx> Mir<'tcx> {

#[inline]
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
self.cache.invalidate();
&mut self.basic_blocks
}

#[inline]
pub fn predecessors(&self) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> {
self.cache.predecessors(self)
}

#[inline]
pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> {
Ref::map(self.predecessors(), |p| &p[bb])
}
}

impl<'tcx> Index<BasicBlock> for Mir<'tcx> {
Expand Down
13 changes: 2 additions & 11 deletions src/librustc_mir/transform/add_call_guards.rs
Expand Up @@ -11,7 +11,6 @@
use rustc::ty::TyCtxt;
use rustc::mir::repr::*;
use rustc::mir::transform::{MirPass, MirSource, Pass};
use rustc::mir::traversal;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};

use pretty;
Expand Down Expand Up @@ -40,16 +39,8 @@ pub struct AddCallGuards;

impl<'tcx> MirPass<'tcx> for AddCallGuards {
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());

// Build the precedecessor map for the MIR
for (_, data) in traversal::preorder(mir) {
if let Some(ref term) = data.terminator {
for &tgt in term.successors().iter() {
pred_count[tgt] += 1;
}
}
}
let pred_count: IndexVec<_, _> =
mir.predecessors().iter().map(|ps| ps.len()).collect();

// We need a place to store the new blocks generated
let mut new_blocks = Vec::new();
Expand Down
11 changes: 2 additions & 9 deletions src/librustc_mir/transform/simplify_cfg.rs
Expand Up @@ -67,15 +67,8 @@ impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
impl<'l> Pass for SimplifyCfg<'l> {}

fn merge_consecutive_blocks(mir: &mut Mir) {
// Build the precedecessor map for the MIR
let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());
for (_, data) in traversal::preorder(mir) {
if let Some(ref term) = data.terminator {
for &tgt in term.successors().iter() {
pred_count[tgt] += 1;
}
}
}
let mut pred_count: IndexVec<_, _> =
mir.predecessors().iter().map(|ps| ps.len()).collect();

loop {
let mut changed = false;
Expand Down

0 comments on commit 6405527

Please sign in to comment.