From 6405527ded784289b4e77d531b57e010cd5fae52 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 7 Jun 2016 22:02:08 +0300 Subject: [PATCH] add a cache for MIR predecessors --- src/librustc/lib.rs | 1 + src/librustc/mir/cache.rs | 69 +++++++++++++++++++ src/librustc/mir/repr.rs | 20 +++++- src/librustc_mir/transform/add_call_guards.rs | 13 +--- src/librustc_mir/transform/simplify_cfg.rs | 11 +-- 5 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 src/librustc/mir/cache.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 301c6e3dd1c4..bc24b54a5c7a 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -102,6 +102,7 @@ pub mod middle { } pub mod mir { + mod cache; pub mod repr; pub mod tcx; pub mod visit; diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs new file mode 100644 index 000000000000..138fed2d64e2 --- /dev/null +++ b/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 or the MIT license +// , 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>>> +} + + +impl serialize::Encodable for Cache { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + serialize::Encodable::encode(&(), s) + } +} + +impl serialize::Decodable for Cache { + fn decode(d: &mut D) -> Result { + 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>> { + 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> { + 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 +} diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index 7394d0081ed8..dad330aa59ea 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -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, @@ -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 @@ -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() } } @@ -124,8 +131,19 @@ impl<'tcx> Mir<'tcx> { #[inline] pub fn basic_blocks_mut(&mut self) -> &mut IndexVec> { + self.cache.invalidate(); &mut self.basic_blocks } + + #[inline] + pub fn predecessors(&self) -> Ref>> { + self.cache.predecessors(self) + } + + #[inline] + pub fn predecessors_for(&self, bb: BasicBlock) -> Ref> { + Ref::map(self.predecessors(), |p| &p[bb]) + } } impl<'tcx> Index for Mir<'tcx> { diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index dee9227fd9b0..63e975128c79 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -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; @@ -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(); diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs index fcc822499532..9cee6b11c07c 100644 --- a/src/librustc_mir/transform/simplify_cfg.rs +++ b/src/librustc_mir/transform/simplify_cfg.rs @@ -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;