Skip to content

Commit

Permalink
add graph algorithms and add dominator to cache
Browse files Browse the repository at this point in the history
  • Loading branch information
scottcarr committed Jun 9, 2016
1 parent ee00760 commit 8ed531b
Show file tree
Hide file tree
Showing 16 changed files with 1,015 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub mod mir {
pub mod transform;
pub mod traversal;
pub mod mir_map;
pub mod mir_cfg;
}

pub mod session;
Expand Down
22 changes: 19 additions & 3 deletions src/librustc/mir/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@

use std::cell::{Ref, RefCell};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::graph_algorithms::dominators::{Dominators, dominators};
use mir::mir_cfg::MirCfg;

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

use rustc_serialize as serialize;

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


Expand All @@ -33,11 +36,11 @@ impl serialize::Decodable for Cache {
}
}


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

Expand All @@ -53,6 +56,14 @@ impl Cache {

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

pub fn dominators(&self, mir: &Mir) -> Ref<Dominators<MirCfg>> {
if self.dominators.borrow().is_none() {
*self.dominators.borrow_mut() = Some(calculate_dominators(mir, self));
}

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

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

result
}

fn calculate_dominators(mir: &Mir, cache: &Cache) -> Dominators<MirCfg> {
let m = MirCfg::new(mir, cache);
dominators(&m)
}
78 changes: 78 additions & 0 deletions src/librustc/mir/mir_cfg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// 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::{iter, slice};
use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::graph_algorithms::{Graph, GraphPredecessors, GraphSuccessors};
use mir::repr::{Mir, BasicBlock, START_BLOCK};
use mir::cache::Cache;

impl MirCfg {
pub fn new<'a, 'tcx>(mir: &Mir, cache: &Cache) -> Self {
MirCfg {
predecessors: cache.predecessors(mir).clone(),
successors: calculate_successors(mir),
n_nodes: mir.basic_blocks().len(),
start_node: START_BLOCK,
}
}
}

#[derive(Clone, Debug)]
pub struct MirCfg {
predecessors: IndexVec<BasicBlock,Vec<BasicBlock>>,
successors: IndexVec<BasicBlock,Vec<BasicBlock>>,
start_node: BasicBlock,
n_nodes: usize,
}

impl Graph for MirCfg {

type Node = BasicBlock;

fn num_nodes(&self) -> usize { self.n_nodes }

fn start_node(&self) -> Self::Node { self.start_node }

fn predecessors<'graph>(&'graph self, node: Self::Node)
-> <Self as GraphPredecessors<'graph>>::Iter
{
self.predecessors[node].iter().cloned()
}
fn successors<'graph>(&'graph self, node: Self::Node)
-> <Self as GraphSuccessors<'graph>>::Iter
{
self.successors[node].iter().cloned()
}
}

impl<'g> GraphPredecessors<'g> for MirCfg {
type Item = BasicBlock;
type Iter = iter::Cloned<slice::Iter<'g, BasicBlock>>;
}

impl<'g> GraphSuccessors<'g> for MirCfg {
type Item = BasicBlock;
type Iter = iter::Cloned<slice::Iter<'g, BasicBlock>>;
}

fn calculate_successors<'a, 'tcx>(mir: &'a Mir<'tcx>) -> IndexVec<BasicBlock, Vec<BasicBlock>> {
let mut successors = IndexVec::from_elem(vec![], mir.basic_blocks());
for (bb, data) in mir.basic_blocks().iter_enumerated() {
if let Some(ref term) = data.terminator {
successors[bb].append(term.successors().to_mut());
}
}
for ss in successors.iter_mut() {
ss.sort();
ss.dedup();
}
successors
}
19 changes: 19 additions & 0 deletions src/librustc/mir/repr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use graphviz::IntoCow;
use middle::const_val::ConstVal;
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::graph_algorithms::NodeIndex;
use hir::def_id::DefId;
use ty::subst::Substs;
use ty::{self, AdtDef, ClosureSubsts, FnOutput, Region, Ty};
Expand Down Expand Up @@ -162,6 +163,24 @@ impl<'tcx> IndexMut<BasicBlock> for Mir<'tcx> {
}
}

impl From<usize> for BasicBlock {
fn from(n: usize) -> BasicBlock {
assert!(n < (u32::MAX as usize));
BasicBlock(n as u32)
}
}
impl Into<usize> for BasicBlock {
fn into(self: BasicBlock) -> usize {
self.index()
}
}

impl NodeIndex for BasicBlock {
fn as_usize(self) -> usize {
self.index()
}
}

/// Grouped information about the source code origin of a MIR entity.
/// Intended to be inspected by diagnostics and debuginfo.
/// Most passes can work with it as a whole, within a single function.
Expand Down
Loading

0 comments on commit 8ed531b

Please sign in to comment.