Use a bforest::Map for the predecessors in the CFG.

Like before, we store a redundant EBB with each predecessor instruction
which allows invalidate_ebb_successors() to clean up the successor's
predecessor lists even after instructions have been moved around in the
layout.
This commit is contained in:
Jakob Stoklund Olesen
2017-11-22 13:52:42 -08:00
parent a960730add
commit 95bdf91e3e

View File

@@ -28,7 +28,6 @@ use ir::{Function, Inst, Ebb};
use ir::instructions::BranchInfo;
use entity::EntityMap;
use std::mem;
use std::slice;
/// A basic block denoted by its enclosing Ebb and last instruction.
pub type BasicBlock = (Ebb, Inst);
@@ -36,12 +35,23 @@ pub type BasicBlock = (Ebb, Inst);
/// A container for the successors and predecessors of some Ebb.
#[derive(Clone, Default)]
pub struct CFGNode {
/// Instructions that can branch or jump to this EBB.
///
/// This maps branch instruction -> predecessor EBB which is redundant since the EBB containing
/// the branch instruction is available from the `layout.inst_ebb()` method. We store the
/// redundant information because:
///
/// 1. Many `pred_iter()` consumers want the EBB anyway, so it is handily available.
/// 2. The `invalidate_ebb_successors()` may be called *after* branches have been removed from
/// their EBB, but we still need to remove them form the old EBB predecessor map.
///
/// The redundant EBB stored here is always consistent with the CFG successor lists, even after
/// the IR has been edited.
pub predecessors: bforest::Map<Inst, Ebb, ()>,
/// Set of EBBs that are the targets of branches and jumps in this EBB.
/// The set is ordered by EBB number, indicated by the `()` comparator type.
pub successors: bforest::Set<Ebb, ()>,
/// Basic blocks that can branch or jump to this EBB.
pub predecessors: Vec<BasicBlock>,
}
/// The Control Flow Graph maintains a mapping of ebbs to their predecessors
@@ -49,6 +59,7 @@ pub struct CFGNode {
/// extended basic blocks.
pub struct ControlFlowGraph {
data: EntityMap<Ebb, CFGNode>,
pred_forest: bforest::MapForest<Inst, Ebb, ()>,
succ_forest: bforest::SetForest<Ebb, ()>,
valid: bool,
}
@@ -59,6 +70,7 @@ impl ControlFlowGraph {
Self {
data: EntityMap::new(),
valid: false,
pred_forest: bforest::MapForest::new(),
succ_forest: bforest::SetForest::new(),
}
}
@@ -66,6 +78,7 @@ impl ControlFlowGraph {
/// Clear all data structures in this control flow graph.
pub fn clear(&mut self) {
self.data.clear();
self.pred_forest.clear();
self.succ_forest.clear();
self.valid = false;
}
@@ -113,7 +126,10 @@ impl ControlFlowGraph {
// our iteration over successors.
let mut successors = mem::replace(&mut self.data[ebb].successors, Default::default());
for succ in successors.iter(&self.succ_forest) {
self.data[succ].predecessors.retain(|&(e, _)| e != ebb);
self.data[succ].predecessors.retain(
&mut self.pred_forest,
|_, &mut e| e != ebb,
);
}
successors.clear(&mut self.succ_forest);
}
@@ -136,12 +152,17 @@ impl ControlFlowGraph {
&mut self.succ_forest,
&(),
);
self.data[to].predecessors.push(from);
self.data[to].predecessors.insert(
from.1,
from.0,
&mut self.pred_forest,
&(),
);
}
/// Get an iterator over the CFG predecessors to `ebb`.
pub fn pred_iter(&self, ebb: Ebb) -> PredIter {
PredIter(self.data[ebb].predecessors.iter())
PredIter(self.data[ebb].predecessors.iter(&self.pred_forest))
}
/// Get an iterator over the CFG successors to `ebb`.
@@ -163,13 +184,13 @@ impl ControlFlowGraph {
/// An iterator over EBB predecessors. The iterator type is `BasicBlock`.
///
/// Each predecessor is an instruction that branches to the EBB.
pub struct PredIter<'a>(slice::Iter<'a, BasicBlock>);
pub struct PredIter<'a>(bforest::MapIter<'a, Inst, Ebb, ()>);
impl<'a> Iterator for PredIter<'a> {
type Item = BasicBlock;
fn next(&mut self) -> Option<BasicBlock> {
self.0.next().cloned()
self.0.next().map(|(i, e)| (e, i))
}
}