add a cache for MIR predecessors
This commit is contained in:
parent
e3af9fa490
commit
6405527ded
5 changed files with 93 additions and 21 deletions
|
|
@ -102,6 +102,7 @@ pub mod middle {
|
|||
}
|
||||
|
||||
pub mod mir {
|
||||
mod cache;
|
||||
pub mod repr;
|
||||
pub mod tcx;
|
||||
pub mod visit;
|
||||
|
|
|
|||
69
src/librustc/mir/cache.rs
Normal file
69
src/librustc/mir/cache.rs
Normal file
|
|
@ -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,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<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> {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue