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

@@ -47,6 +47,7 @@ pub struct CFGNode {
pub struct ControlFlowGraph {
entry_block: Option<Ebb>,
data: EntityMap<Ebb, CFGNode>,
valid: bool,
}
impl ControlFlowGraph {
@@ -55,6 +56,7 @@ impl ControlFlowGraph {
ControlFlowGraph {
entry_block: None,
data: EntityMap::new(),
valid: false,
}
}
@@ -76,6 +78,8 @@ impl ControlFlowGraph {
for ebb in &func.layout {
self.compute_ebb(func, ebb);
}
self.valid = true;
}
fn compute_ebb(&mut self, func: &Function, ebb: Ebb) {
@@ -113,6 +117,7 @@ impl ControlFlowGraph {
/// more expensive `compute`, and should be used when we know we don't need to recompute the CFG
/// from scratch, but rather that our changes have been restricted to specific EBBs.
pub fn recompute_ebb(&mut self, func: &Function, ebb: Ebb) {
debug_assert!(self.is_valid());
self.invalidate_ebb_successors(ebb);
self.compute_ebb(func, ebb);
}
@@ -124,11 +129,13 @@ impl ControlFlowGraph {
/// Get the CFG predecessor basic blocks to `ebb`.
pub fn get_predecessors(&self, ebb: Ebb) -> &[BasicBlock] {
debug_assert!(self.is_valid());
&self.data[ebb].predecessors
}
/// Get the CFG successors to `ebb`.
pub fn get_successors(&self, ebb: Ebb) -> &[Ebb] {
debug_assert!(self.is_valid());
&self.data[ebb].successors
}
@@ -138,15 +145,7 @@ impl ControlFlowGraph {
/// `compute()` method has been called since the last `clear()`. It does not check that the
/// CFG is consistent with the function.
pub fn is_valid(&self) -> bool {
self.entry_block.is_some()
}
/// Conveneince function to call `compute` if `compute` hasn't been called
/// since the last `clear()`.
pub fn ensure(&mut self, func: &Function) {
if !self.is_valid() {
self.compute(func)
}
self.valid
}
}