Skip to content

Commit 72f2715

Browse files
committed
add a cache for MIR predecessors
1 parent 4666fec commit 72f2715

File tree

5 files changed

+93
-22
lines changed

5 files changed

+93
-22
lines changed

src/librustc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ pub mod middle {
102102
}
103103

104104
pub mod mir {
105+
mod cache;
105106
pub mod repr;
106107
pub mod tcx;
107108
pub mod visit;

src/librustc/mir/cache.rs

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::cell::{Ref, RefCell};
12+
use rustc_data_structures::indexed_vec::IdxVec;
13+
14+
use mir::repr::{Mir, BasicBlock};
15+
16+
use rustc_serialize as serialize;
17+
18+
#[derive(Clone)]
19+
pub struct Cache {
20+
predecessors: RefCell<Option<IdxVec<BasicBlock, Vec<BasicBlock>>>>
21+
}
22+
23+
24+
impl serialize::Encodable for Cache {
25+
fn encode<S: serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
26+
serialize::Encodable::encode(&(), s)
27+
}
28+
}
29+
30+
impl serialize::Decodable for Cache {
31+
fn decode<D: serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
32+
serialize::Decodable::decode(d).map(|_v: ()| Self::new())
33+
}
34+
}
35+
36+
37+
impl Cache {
38+
pub fn new() -> Self {
39+
Cache {
40+
predecessors: RefCell::new(None)
41+
}
42+
}
43+
44+
pub fn invalidate(&self) {
45+
// FIXME: consider being more fine-grained
46+
*self.predecessors.borrow_mut() = None;
47+
}
48+
49+
pub fn predecessors(&self, mir: &Mir) -> Ref<IdxVec<BasicBlock, Vec<BasicBlock>>> {
50+
if self.predecessors.borrow().is_none() {
51+
*self.predecessors.borrow_mut() = Some(calculate_predecessors(mir));
52+
}
53+
54+
Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
55+
}
56+
}
57+
58+
fn calculate_predecessors(mir: &Mir) -> IdxVec<BasicBlock, Vec<BasicBlock>> {
59+
let mut result = IdxVec::from_elem(vec![], mir.basic_blocks());
60+
for (bb, data) in mir.basic_blocks().iter_enumerated() {
61+
if let Some(ref term) = data.terminator {
62+
for &tgt in term.successors().iter() {
63+
result[tgt].push(bb);
64+
}
65+
}
66+
}
67+
68+
result
69+
}

src/librustc/mir/repr.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,15 @@ use rustc_back::slice;
2020
use hir::InlineAsm;
2121
use std::ascii;
2222
use std::borrow::{Cow};
23+
use std::cell::Ref;
2324
use std::fmt::{self, Debug, Formatter, Write};
2425
use std::{iter, u32};
2526
use std::ops::{Index, IndexMut};
2627
use syntax::ast::{self, Name};
2728
use syntax::codemap::Span;
2829

30+
use super::cache::Cache;
31+
2932
macro_rules! newtype_index {
3033
($name:ident, $debug_name:expr) => (
3134
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord,
@@ -88,6 +91,9 @@ pub struct Mir<'tcx> {
8891

8992
/// A span representing this MIR, for error reporting
9093
pub span: Span,
94+
95+
/// A cache for various calculations
96+
cache: Cache
9197
}
9298

9399
/// where execution begins
@@ -113,7 +119,8 @@ impl<'tcx> Mir<'tcx> {
113119
arg_decls: arg_decls,
114120
temp_decls: temp_decls,
115121
upvar_decls: upvar_decls,
116-
span: span
122+
span: span,
123+
cache: Cache::new()
117124
}
118125
}
119126

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

125132
#[inline]
126133
pub fn basic_blocks_mut(&mut self) -> &mut IdxVec<BasicBlock, BasicBlockData<'tcx>> {
134+
self.cache.invalidate();
127135
&mut self.basic_blocks
128136
}
137+
138+
#[inline]
139+
pub fn predecessors(&self) -> Ref<IdxVec<BasicBlock, Vec<BasicBlock>>> {
140+
self.cache.predecessors(self)
141+
}
142+
143+
#[inline]
144+
pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> {
145+
Ref::map(self.predecessors(), |p| &p[bb])
146+
}
129147
}
130148

131149
impl<'tcx> Index<BasicBlock> for Mir<'tcx> {

src/librustc_mir/transform/add_call_guards.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ use rustc_data_structures::indexed_vec::{Idx, IdxVec};
1616

1717
use pretty;
1818

19-
use traversal;
20-
2119
pub struct AddCallGuards;
2220

2321
/**
@@ -42,16 +40,8 @@ pub struct AddCallGuards;
4240

4341
impl<'tcx> MirPass<'tcx> for AddCallGuards {
4442
fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
45-
let mut pred_count = IdxVec::from_elem(0u32, mir.basic_blocks());
46-
47-
// Build the precedecessor map for the MIR
48-
for (_, data) in traversal::preorder(mir) {
49-
if let Some(ref term) = data.terminator {
50-
for &tgt in term.successors().iter() {
51-
pred_count[tgt] += 1;
52-
}
53-
}
54-
}
43+
let pred_count: IdxVec<_, _> =
44+
mir.predecessors().iter().map(|ps| ps.len()).collect();
5545

5646
// We need a place to store the new blocks generated
5747
let mut new_blocks = Vec::new();

src/librustc_mir/transform/simplify_cfg.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,8 @@ impl<'l, 'tcx> MirPass<'tcx> for SimplifyCfg<'l> {
6868
impl<'l> Pass for SimplifyCfg<'l> {}
6969

7070
fn merge_consecutive_blocks(mir: &mut Mir) {
71-
// Build the precedecessor map for the MIR
72-
let mut pred_count = IdxVec::from_elem(0u32, mir.basic_blocks());
73-
for (_, data) in traversal::preorder(mir) {
74-
if let Some(ref term) = data.terminator {
75-
for &tgt in term.successors().iter() {
76-
pred_count[tgt] += 1;
77-
}
78-
}
79-
}
71+
let mut pred_count: IdxVec<_, _> =
72+
mir.predecessors().iter().map(|ps| ps.len()).collect();
8073

8174
loop {
8275
let mut changed = false;

0 commit comments

Comments
 (0)