Make passes assert their dependencies consistently. (#156)

* Make passes assert their dependencies consistently.

This avoids ambiguity about whose responsibility it is to run
to compute cfg, domtree, and loop_analysis data.

* Reset the `valid` flag in DominatorTree's `clear()`.

* Remove the redundant assert from DominatorTree::with_function.

* Remove the message strings from obvious asserts.

This avoids having them spill out into multiple lines.

* Refactor calls to `compute` on `Context` objects into helper functions.
This commit is contained in:
Dan Gohman
2017-09-14 14:38:53 -07:00
committed by GitHub
parent 39992014e0
commit bbe056bf9d
15 changed files with 72 additions and 43 deletions

View File

@@ -37,6 +37,8 @@ pub struct DominatorTree {
// Scratch memory used by `compute_postorder()`.
stack: Vec<Ebb>,
valid: bool,
}
/// Methods for querying the dominator tree.
@@ -51,6 +53,7 @@ impl DominatorTree {
/// Note that this post-order is not updated automatically when the CFG is modified. It is
/// computed from scratch and cached by `compute()`.
pub fn cfg_postorder(&self) -> &[Ebb] {
debug_assert!(self.is_valid());
&self.postorder
}
@@ -203,6 +206,7 @@ impl DominatorTree {
nodes: EntityMap::new(),
postorder: Vec::new(),
stack: Vec::new(),
valid: false,
}
}
@@ -215,8 +219,10 @@ impl DominatorTree {
/// Reset and compute a CFG post-order and dominator tree.
pub fn compute(&mut self, func: &Function, cfg: &ControlFlowGraph) {
debug_assert!(cfg.is_valid());
self.compute_postorder(func, cfg);
self.compute_domtree(func, cfg);
self.valid = true;
}
/// Clear the data structures used to represent the dominator tree. This will leave the tree in
@@ -225,6 +231,7 @@ impl DominatorTree {
self.nodes.clear();
self.postorder.clear();
assert!(self.stack.is_empty());
self.valid = false;
}
/// Check if the dominator tree is in a valid state.
@@ -233,15 +240,7 @@ impl DominatorTree {
/// `compute()` method has been called since the last `clear()`. It does not check that the
/// dominator tree is consistent with the CFG.
pub fn is_valid(&self) -> bool {
!self.nodes.is_empty()
}
/// Conveneince function to call `compute` if `compute` hasn't been called
/// since the last `clear()`.
pub fn ensure(&mut self, func: &Function, cfg: &ControlFlowGraph) {
if !self.is_valid() {
self.compute(func, cfg)
}
self.valid
}
/// Reset all internal data structures and compute a post-order for `cfg`.
@@ -437,6 +436,7 @@ mod test {
fn empty() {
let func = Function::new();
let cfg = ControlFlowGraph::with_function(&func);
debug_assert!(cfg.is_valid());
let dtree = DominatorTree::with_function(&func, &cfg);
assert_eq!(0, dtree.nodes.keys().count());
assert_eq!(dtree.cfg_postorder(), &[]);