Clean up the CFG representation.

This commit is contained in:
Morgan Phillips
2016-07-31 21:31:18 -07:00
parent dae349371f
commit a8beb542a5
2 changed files with 15 additions and 30 deletions

View File

@@ -26,13 +26,13 @@ use ir::Function;
use ir::entities::{Inst, Ebb}; use ir::entities::{Inst, Ebb};
use ir::instructions::BranchInfo; use ir::instructions::BranchInfo;
use entity_map::EntityMap; use entity_map::EntityMap;
use std::collections::{HashSet, BTreeMap}; use std::collections::HashSet;
/// A basic block denoted by its enclosing Ebb and last instruction. /// A basic block denoted by its enclosing Ebb and last instruction.
pub type BasicBlock = (Ebb, Inst); pub type BasicBlock = (Ebb, Inst);
/// A container for the successors and predecessors of some Ebb. /// A container for the successors and predecessors of some Ebb.
#[derive(Debug)] #[derive(Debug, Clone, Default)]
pub struct CFGNode { pub struct CFGNode {
pub successors: Vec<Ebb>, pub successors: Vec<Ebb>,
pub predecessors: Vec<BasicBlock>, pub predecessors: Vec<BasicBlock>,
@@ -62,27 +62,19 @@ impl ControlFlowGraph {
pub fn new(func: &Function) -> ControlFlowGraph { pub fn new(func: &Function) -> ControlFlowGraph {
let mut cfg = ControlFlowGraph { let mut cfg = ControlFlowGraph {
data: EntityMap::new(), data: EntityMap::with_capacity(func.dfg.num_ebbs()),
entry_block: func.layout.entry_block(), entry_block: func.layout.entry_block(),
}; };
// Even ebbs without predecessors should show up in the CFG, albeit
// with no entires.
for _ in &func.layout {
cfg.push_ebb();
}
for ebb in &func.layout { for ebb in &func.layout {
for inst in func.layout.ebb_insts(ebb) { for inst in func.layout.ebb_insts(ebb) {
match func.dfg[inst].analyze_branch() { match func.dfg[inst].analyze_branch() {
BranchInfo::SingleDest(dest, _) => { BranchInfo::SingleDest(dest, _) => {
cfg.add_successor(ebb, dest); cfg.add_edge((ebb, inst), dest);
cfg.add_predecessor(dest, (ebb, inst));
} }
BranchInfo::Table(jt) => { BranchInfo::Table(jt) => {
for (_, dest) in func.jump_tables[jt].entries() { for (_, dest) in func.jump_tables[jt].entries() {
cfg.add_successor(ebb, dest); cfg.add_edge((ebb, inst), dest);
cfg.add_predecessor(dest, (ebb, inst));
} }
} }
BranchInfo::NotABranch => {} BranchInfo::NotABranch => {}
@@ -92,19 +84,12 @@ impl ControlFlowGraph {
cfg cfg
} }
pub fn push_ebb(&mut self) { fn add_edge(&mut self, from: BasicBlock, to: Ebb) {
self.data.push(CFGNode::new()); self.data[from.0].successors.push(to);
self.data[to].predecessors.push(from);
} }
pub fn add_successor(&mut self, from: Ebb, to: Ebb) { fn get_predecessors(&self, ebb: Ebb) -> &Vec<BasicBlock> {
self.data[from].successors.push(to);
}
pub fn add_predecessor(&mut self, ebb: Ebb, predecessor: BasicBlock) {
self.data[ebb].predecessors.push(predecessor);
}
pub fn get_predecessors(&self, ebb: Ebb) -> &Vec<BasicBlock> {
&self.data[ebb].predecessors &self.data[ebb].predecessors
} }
@@ -114,10 +99,10 @@ impl ControlFlowGraph {
/// Return ebbs in reverse postorder along with a mapping of /// Return ebbs in reverse postorder along with a mapping of
/// the ebb to its [post]order of visitation. /// the ebb to its [post]order of visitation.
pub fn reverse_postorder_ebbs(&self) -> BTreeMap<Ebb, usize> { pub fn reverse_postorder_ebbs(&self) -> EntityMap<Ebb, usize> {
let entry_block = match self.entry_block { let entry_block = match self.entry_block {
None => { None => {
return BTreeMap::new(); return EntityMap::new();
} }
Some(eb) => eb, Some(eb) => eb,
}; };
@@ -146,10 +131,10 @@ impl ControlFlowGraph {
} }
postorder.reverse(); postorder.reverse();
let mut result = BTreeMap::new(); let mut result = EntityMap::with_capacity(postorder.len());
for (offset, ebb) in postorder.iter().enumerate() { for (offset, ebb) in postorder.iter().enumerate() {
let i = postorder.len() - offset; let i = postorder.len() - offset;
result.insert(ebb.clone(), i); result[ebb.clone()] = i;
} }
result result
} }

View File

@@ -14,8 +14,8 @@ fn test_reverse_postorder_traversal(function_source: &str, ebb_order: Vec<u32>)
let reverse_postorder_ebbs = cfg.reverse_postorder_ebbs(); let reverse_postorder_ebbs = cfg.reverse_postorder_ebbs();
assert_eq!(reverse_postorder_ebbs.len(), ebbs.len()); assert_eq!(reverse_postorder_ebbs.len(), ebbs.len());
for (ebb, key) in reverse_postorder_ebbs { for ebb in reverse_postorder_ebbs.keys() {
assert_eq!(ebb, ebbs[ebbs.len() - key]); assert_eq!(ebb, ebbs[ebbs.len() - reverse_postorder_ebbs[ebb]]);
} }
} }