From f81b5bfbe977f0ef73a7ab0392b5395278f41b66 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Sat, 25 Feb 2023 11:31:49 -0800 Subject: [PATCH] Fuel mechanism to help debug opts --- src/ir/func.rs | 9 +++++---- src/passes.rs | 15 +++++++++++++++ src/passes/basic_opt.rs | 25 +++++++++++++++++++------ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/ir/func.rs b/src/ir/func.rs index 826173a..aefd907 100644 --- a/src/ir/func.rs +++ b/src/ir/func.rs @@ -3,6 +3,7 @@ use crate::cfg::CFGInfo; use crate::entity::{EntityRef, EntityVec, PerEntity}; use crate::frontend::parse_body; use crate::ir::SourceLoc; +use crate::passes::Fuel; use anyhow::Result; #[derive(Clone, Debug)] @@ -32,10 +33,10 @@ impl<'a> FuncDecl<'a> { } } - pub fn optimize(&mut self) { + pub fn optimize(&mut self, fuel: &mut Fuel) { match self { FuncDecl::Body(_, _, body) => { - body.optimize(); + body.optimize(fuel); } _ => {} } @@ -131,9 +132,9 @@ impl FunctionBody { } } - pub fn optimize(&mut self) { + pub fn optimize(&mut self, fuel: &mut Fuel) { let cfg = crate::cfg::CFGInfo::new(self); - crate::passes::basic_opt::gvn(self, &cfg); + crate::passes::basic_opt::gvn(self, &cfg, fuel); crate::passes::resolve_aliases::run(self); crate::passes::ssa::run(self, &cfg); } diff --git a/src/passes.rs b/src/passes.rs index 46aa889..11dc04c 100644 --- a/src/passes.rs +++ b/src/passes.rs @@ -7,3 +7,18 @@ pub mod maxssa; pub mod resolve_aliases; pub mod ssa; pub mod trace; + +#[derive(Clone, Debug)] +pub struct Fuel { + pub remaining: u64, +} +impl Fuel { + pub fn consume(&mut self) -> bool { + if self.remaining == 0 { + false + } else { + self.remaining -= 1; + true + } + } +} diff --git a/src/passes/basic_opt.rs b/src/passes/basic_opt.rs index dd2e9d5..828fb0f 100644 --- a/src/passes/basic_opt.rs +++ b/src/passes/basic_opt.rs @@ -4,19 +4,28 @@ use crate::cfg::CFGInfo; use crate::interp::{const_eval, ConstVal}; use crate::ir::*; use crate::passes::dom_pass::{dom_pass, DomtreePass}; +use crate::passes::Fuel; use crate::scoped_map::ScopedMap; use crate::Operator; -pub fn gvn(body: &mut FunctionBody, cfg: &CFGInfo) { - dom_pass::(body, cfg, &mut GVNPass::default()); +pub fn gvn(body: &mut FunctionBody, cfg: &CFGInfo, fuel: &mut Fuel) { + dom_pass::>( + body, + cfg, + &mut GVNPass { + map: ScopedMap::default(), + fuel, + }, + ); } -#[derive(Clone, Debug, Default)] -struct GVNPass { +#[derive(Debug)] +struct GVNPass<'a> { map: ScopedMap, + fuel: &'a mut Fuel, } -impl DomtreePass for GVNPass { +impl<'a> DomtreePass for GVNPass<'a> { fn enter(&mut self, block: Block, body: &mut FunctionBody) { self.map.push_level(); self.optimize(block, body); @@ -34,10 +43,14 @@ fn value_is_pure(value: Value, body: &FunctionBody) -> bool { } } -impl GVNPass { +impl<'a> GVNPass<'a> { fn optimize(&mut self, block: Block, body: &mut FunctionBody) { let mut i = 0; while i < body.blocks[block].insts.len() { + if !self.fuel.consume() { + return; + } + let inst = body.blocks[block].insts[i]; i += 1; if value_is_pure(inst, body) {