diff --git a/lib/cretonne/src/context.rs b/lib/cretonne/src/context.rs index 7fec7ea0fb..6f80f16056 100644 --- a/lib/cretonne/src/context.rs +++ b/lib/cretonne/src/context.rs @@ -63,7 +63,7 @@ impl Context { /// /// Returns the size of the function's code. pub fn compile(&mut self, isa: &TargetIsa) -> Result { - self.flowgraph(); + self.cfg.compute(&self.func); self.verify_if(isa)?; self.legalize(isa)?; @@ -103,6 +103,8 @@ impl Context { /// Run the legalizer for `isa` on the function. pub fn legalize(&mut self, isa: &TargetIsa) -> CtonResult { + // Legalization invalidates the domtree by mutating the CFG. + self.domtree.clear(); legalize_function(&mut self.func, &mut self.cfg, isa); self.verify_if(isa) } @@ -113,6 +115,13 @@ impl Context { self.domtree.compute(&self.func, &self.cfg); } + /// Ensure that a valid domtree exists. + pub fn ensure_domtree(&mut self) { + if !self.domtree.is_valid() { + self.domtree.compute(&self.func, &self.cfg); + } + } + /// Perform simple GVN on the function. pub fn simple_gvn(&mut self) -> CtonResult { do_simple_gvn(&mut self.func, &mut self.cfg); @@ -123,6 +132,7 @@ impl Context { /// Perform LICM on the function. pub fn licm(&mut self) -> CtonResult { + self.ensure_domtree(); do_licm(&mut self.func, &mut self.cfg, &mut self.domtree, @@ -132,6 +142,7 @@ impl Context { /// Run the register allocator. pub fn regalloc(&mut self, isa: &TargetIsa) -> CtonResult { + self.ensure_domtree(); self.regalloc .run(isa, &mut self.func, &self.cfg, &self.domtree) } diff --git a/lib/cretonne/src/dominator_tree.rs b/lib/cretonne/src/dominator_tree.rs index bb80bd3687..067142b0f2 100644 --- a/lib/cretonne/src/dominator_tree.rs +++ b/lib/cretonne/src/dominator_tree.rs @@ -205,14 +205,30 @@ impl DominatorTree { self.compute_domtree(func, cfg); } + /// Clear the data structures used to represent the dominator tree. This will leave the tree in + /// a state where `is_valid()` returns false. + pub fn clear(&mut self) { + self.nodes.clear(); + self.postorder.clear(); + assert!(self.stack.is_empty()); + } + + /// Check if the dominator tree is in a valid state. + /// + /// Note that this doesn't perform any kind of validity checks. It simply checks if the + /// `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() + } + /// Reset all internal data structures and compute a post-order for `cfg`. /// /// This leaves `rpo_number == 1` for all reachable EBBs, 0 for unreachable ones. fn compute_postorder(&mut self, func: &Function, cfg: &ControlFlowGraph) { - self.nodes.clear(); + self.clear(); self.nodes.resize(func.dfg.num_ebbs()); - self.postorder.clear(); - assert!(self.stack.is_empty()); // During this algorithm only, use `rpo_number` to hold the following state: // diff --git a/lib/cretonne/src/verifier/mod.rs b/lib/cretonne/src/verifier/mod.rs index 4c8fcd04a5..ca1f2a8f09 100644 --- a/lib/cretonne/src/verifier/mod.rs +++ b/lib/cretonne/src/verifier/mod.rs @@ -134,7 +134,9 @@ pub fn verify_context(func: &Function, -> Result { let verifier = Verifier::new(func, isa); verifier.cfg_integrity(cfg)?; - verifier.domtree_integrity(domtree)?; + if domtree.is_valid() { + verifier.domtree_integrity(domtree)?; + } verifier.run() }