Fuel mechanism to help debug opts

This commit is contained in:
Chris Fallin 2023-02-25 11:31:49 -08:00
parent 9031e74abd
commit f81b5bfbe9
3 changed files with 39 additions and 10 deletions

View file

@ -3,6 +3,7 @@ use crate::cfg::CFGInfo;
use crate::entity::{EntityRef, EntityVec, PerEntity}; use crate::entity::{EntityRef, EntityVec, PerEntity};
use crate::frontend::parse_body; use crate::frontend::parse_body;
use crate::ir::SourceLoc; use crate::ir::SourceLoc;
use crate::passes::Fuel;
use anyhow::Result; use anyhow::Result;
#[derive(Clone, Debug)] #[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 { match self {
FuncDecl::Body(_, _, body) => { 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); 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::resolve_aliases::run(self);
crate::passes::ssa::run(self, &cfg); crate::passes::ssa::run(self, &cfg);
} }

View file

@ -7,3 +7,18 @@ pub mod maxssa;
pub mod resolve_aliases; pub mod resolve_aliases;
pub mod ssa; pub mod ssa;
pub mod trace; 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
}
}
}

View file

@ -4,19 +4,28 @@ use crate::cfg::CFGInfo;
use crate::interp::{const_eval, ConstVal}; use crate::interp::{const_eval, ConstVal};
use crate::ir::*; use crate::ir::*;
use crate::passes::dom_pass::{dom_pass, DomtreePass}; use crate::passes::dom_pass::{dom_pass, DomtreePass};
use crate::passes::Fuel;
use crate::scoped_map::ScopedMap; use crate::scoped_map::ScopedMap;
use crate::Operator; use crate::Operator;
pub fn gvn(body: &mut FunctionBody, cfg: &CFGInfo) { pub fn gvn(body: &mut FunctionBody, cfg: &CFGInfo, fuel: &mut Fuel) {
dom_pass::<GVNPass>(body, cfg, &mut GVNPass::default()); dom_pass::<GVNPass<'_>>(
body,
cfg,
&mut GVNPass {
map: ScopedMap::default(),
fuel,
},
);
} }
#[derive(Clone, Debug, Default)] #[derive(Debug)]
struct GVNPass { struct GVNPass<'a> {
map: ScopedMap<ValueDef, Value>, map: ScopedMap<ValueDef, Value>,
fuel: &'a mut Fuel,
} }
impl DomtreePass for GVNPass { impl<'a> DomtreePass for GVNPass<'a> {
fn enter(&mut self, block: Block, body: &mut FunctionBody) { fn enter(&mut self, block: Block, body: &mut FunctionBody) {
self.map.push_level(); self.map.push_level();
self.optimize(block, body); 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) { fn optimize(&mut self, block: Block, body: &mut FunctionBody) {
let mut i = 0; let mut i = 0;
while i < body.blocks[block].insts.len() { while i < body.blocks[block].insts.len() {
if !self.fuel.consume() {
return;
}
let inst = body.blocks[block].insts[i]; let inst = body.blocks[block].insts[i];
i += 1; i += 1;
if value_is_pure(inst, body) { if value_is_pure(inst, body) {