From e2f0fe58d128662a66624833619bd4dbee16b874 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 12 Sep 2017 16:15:22 -0700 Subject: [PATCH] Move logic out of `cton-util wasm`. Give LoopAnalysis `is_valid` and `ensure` functions similar to DominatorTree and others, so that it can be computed on demand in the same way. This removes the last need for src/wasm.rs to have embedded knowledge of the dependencies of the passes it's running. --- cranelift/src/wasm.rs | 15 +-------------- lib/cretonne/src/licm.rs | 2 +- lib/cretonne/src/loop_analysis.rs | 22 +++++++++++++++++++++- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index 350a15d51a..4f48ae6d70 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -6,9 +6,6 @@ use cton_wasm::{translate_module, DummyRuntime, WasmRuntime}; use std::path::PathBuf; -use cretonne::loop_analysis::LoopAnalysis; -use cretonne::flowgraph::ControlFlowGraph; -use cretonne::dominator_tree::DominatorTree; use cretonne::Context; use cretonne::verifier; use cretonne::settings::{self, Configurable}; @@ -156,18 +153,8 @@ fn handle_module( vprint!(flag_verbose, "Optimizing... "); terminal.reset().unwrap(); for func in &translation.functions { - let mut il = func.clone(); - let mut loop_analysis = LoopAnalysis::new(); - let mut cfg = ControlFlowGraph::new(); - cfg.compute(&il); - let mut domtree = DominatorTree::new(); - domtree.compute(&mut il, &cfg); - loop_analysis.compute(&mut il, &mut cfg, &mut domtree); let mut context = Context::new(); - context.func = il; - context.cfg = cfg; - context.domtree = domtree; - context.loop_analysis = loop_analysis; + context.func = func.clone(); verifier::verify_context(&context.func, &context.cfg, &context.domtree, None) .map_err(|err| pretty_verifier_error(&context.func, None, err))?; context.licm(); diff --git a/lib/cretonne/src/licm.rs b/lib/cretonne/src/licm.rs index 225cd4d524..107f3f7766 100644 --- a/lib/cretonne/src/licm.rs +++ b/lib/cretonne/src/licm.rs @@ -18,7 +18,7 @@ pub fn do_licm( ) { cfg.ensure(func); domtree.ensure(func, cfg); - loop_analysis.compute(func, cfg, domtree); + loop_analysis.ensure(func, cfg, domtree); for lp in loop_analysis.loops() { // For each loop that we want to optimize we determine the set of loop-invariant // instructions diff --git a/lib/cretonne/src/loop_analysis.rs b/lib/cretonne/src/loop_analysis.rs index 4c87e773a7..9d5e466c16 100644 --- a/lib/cretonne/src/loop_analysis.rs +++ b/lib/cretonne/src/loop_analysis.rs @@ -18,6 +18,7 @@ entity_impl!(Loop, "loop"); /// Loops are referenced by the Loop object, and for each loop you can access its header EBB, /// its eventual parent in the loop tree and all the EBB belonging to the loop. pub struct LoopAnalysis { + valid: bool, loops: PrimaryMap, ebb_loop_map: EntityMap>, } @@ -43,6 +44,7 @@ impl LoopAnalysis { /// a function. pub fn new() -> LoopAnalysis { LoopAnalysis { + valid: false, loops: PrimaryMap::new(), ebb_loop_map: EntityMap::new(), } @@ -100,7 +102,25 @@ impl LoopAnalysis { self.ebb_loop_map.clear(); self.ebb_loop_map.resize(func.dfg.num_ebbs()); self.find_loop_headers(cfg, domtree, &func.layout); - self.discover_loop_blocks(cfg, domtree, &func.layout) + self.discover_loop_blocks(cfg, domtree, &func.layout); + self.valid = true; + } + + /// Check if the loop analysis 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 + /// loop analysis is consistent with the CFG. + pub fn is_valid(&self) -> bool { + self.valid + } + + /// Conveneince function to call `compute` if `compute` hasn't been called + /// since the last `clear()`. + pub fn ensure(&mut self, func: &Function, cfg: &ControlFlowGraph, domtree: &DominatorTree) { + if !self.is_valid() { + self.compute(func, cfg, domtree) + } } // Traverses the CFG in reverse postorder and create a loop object for every EBB having a