Skip to content

Commit 8ed531b

Browse files
committed
add graph algorithms and add dominator to cache
1 parent ee00760 commit 8ed531b

File tree

16 files changed

+1015
-3
lines changed

16 files changed

+1015
-3
lines changed

src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ pub mod mir {
110110
pub mod transform;
111111
pub mod traversal;
112112
pub mod mir_map;
113+
pub mod mir_cfg;
113114
}
114115

115116
pub mod session;

src/librustc/mir/cache.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@
1010

1111
use std::cell::{Ref, RefCell};
1212
use rustc_data_structures::indexed_vec::IndexVec;
13+
use rustc_data_structures::graph_algorithms::dominators::{Dominators, dominators};
14+
use mir::mir_cfg::MirCfg;
1315

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

1618
use rustc_serialize as serialize;
1719

1820
#[derive(Clone)]
1921
pub struct Cache {
20-
predecessors: RefCell<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
22+
predecessors: RefCell<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>,
23+
dominators: RefCell<Option<Dominators<MirCfg>>>,
2124
}
2225

2326

@@ -33,11 +36,11 @@ impl serialize::Decodable for Cache {
3336
}
3437
}
3538

36-
3739
impl Cache {
3840
pub fn new() -> Self {
3941
Cache {
40-
predecessors: RefCell::new(None)
42+
predecessors: RefCell::new(None),
43+
dominators: RefCell::new(None),
4144
}
4245
}
4346

@@ -53,6 +56,14 @@ impl Cache {
5356

5457
Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
5558
}
59+
60+
pub fn dominators(&self, mir: &Mir) -> Ref<Dominators<MirCfg>> {
61+
if self.dominators.borrow().is_none() {
62+
*self.dominators.borrow_mut() = Some(calculate_dominators(mir, self));
63+
}
64+
65+
Ref::map(self.dominators.borrow(), |p| p.as_ref().unwrap())
66+
}
5667
}
5768

5869
fn calculate_predecessors(mir: &Mir) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
@@ -67,3 +78,8 @@ fn calculate_predecessors(mir: &Mir) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
6778

6879
result
6980
}
81+
82+
fn calculate_dominators(mir: &Mir, cache: &Cache) -> Dominators<MirCfg> {
83+
let m = MirCfg::new(mir, cache);
84+
dominators(&m)
85+
}

src/librustc/mir/mir_cfg.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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::{iter, slice};
12+
use rustc_data_structures::indexed_vec::IndexVec;
13+
use rustc_data_structures::graph_algorithms::{Graph, GraphPredecessors, GraphSuccessors};
14+
use mir::repr::{Mir, BasicBlock, START_BLOCK};
15+
use mir::cache::Cache;
16+
17+
impl MirCfg {
18+
pub fn new<'a, 'tcx>(mir: &Mir, cache: &Cache) -> Self {
19+
MirCfg {
20+
predecessors: cache.predecessors(mir).clone(),
21+
successors: calculate_successors(mir),
22+
n_nodes: mir.basic_blocks().len(),
23+
start_node: START_BLOCK,
24+
}
25+
}
26+
}
27+
28+
#[derive(Clone, Debug)]
29+
pub struct MirCfg {
30+
predecessors: IndexVec<BasicBlock,Vec<BasicBlock>>,
31+
successors: IndexVec<BasicBlock,Vec<BasicBlock>>,
32+
start_node: BasicBlock,
33+
n_nodes: usize,
34+
}
35+
36+
impl Graph for MirCfg {
37+
38+
type Node = BasicBlock;
39+
40+
fn num_nodes(&self) -> usize { self.n_nodes }
41+
42+
fn start_node(&self) -> Self::Node { self.start_node }
43+
44+
fn predecessors<'graph>(&'graph self, node: Self::Node)
45+
-> <Self as GraphPredecessors<'graph>>::Iter
46+
{
47+
self.predecessors[node].iter().cloned()
48+
}
49+
fn successors<'graph>(&'graph self, node: Self::Node)
50+
-> <Self as GraphSuccessors<'graph>>::Iter
51+
{
52+
self.successors[node].iter().cloned()
53+
}
54+
}
55+
56+
impl<'g> GraphPredecessors<'g> for MirCfg {
57+
type Item = BasicBlock;
58+
type Iter = iter::Cloned<slice::Iter<'g, BasicBlock>>;
59+
}
60+
61+
impl<'g> GraphSuccessors<'g> for MirCfg {
62+
type Item = BasicBlock;
63+
type Iter = iter::Cloned<slice::Iter<'g, BasicBlock>>;
64+
}
65+
66+
fn calculate_successors<'a, 'tcx>(mir: &'a Mir<'tcx>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
67+
let mut successors = IndexVec::from_elem(vec![], mir.basic_blocks());
68+
for (bb, data) in mir.basic_blocks().iter_enumerated() {
69+
if let Some(ref term) = data.terminator {
70+
successors[bb].append(term.successors().to_mut());
71+
}
72+
}
73+
for ss in successors.iter_mut() {
74+
ss.sort();
75+
ss.dedup();
76+
}
77+
successors
78+
}

src/librustc/mir/repr.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use graphviz::IntoCow;
1212
use middle::const_val::ConstVal;
1313
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
1414
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
15+
use rustc_data_structures::graph_algorithms::NodeIndex;
1516
use hir::def_id::DefId;
1617
use ty::subst::Substs;
1718
use ty::{self, AdtDef, ClosureSubsts, FnOutput, Region, Ty};
@@ -162,6 +163,24 @@ impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
162163
}
163164
}
164165

166+
impl From<usize> for BasicBlock {
167+
fn from(n: usize) -> BasicBlock {
168+
assert!(n < (u32::MAX as usize));
169+
BasicBlock(n as u32)
170+
}
171+
}
172+
impl Into<usize> for BasicBlock {
173+
fn into(self: BasicBlock) -> usize {
174+
self.index()
175+
}
176+
}
177+
178+
impl NodeIndex for BasicBlock {
179+
fn as_usize(self) -> usize {
180+
self.index()
181+
}
182+
}
183+
165184
/// Grouped information about the source code origin of a MIR entity.
166185
/// Intended to be inspected by diagnostics and debuginfo.
167186
/// Most passes can work with it as a whole, within a single function.

0 commit comments

Comments
 (0)