Skip to content

Commit 823406d

Browse files
benchclaude
andcommitted
feat: add optimizer infrastructure and post-lowering structural passes
Add shared optimizer utilities and four post-lowering optimization passes: **Shared utilities** (optimizer/utils.rs): - terminator_successors: Get successor blocks for control flow terminators - build_predecessors: Build predecessor map for dominance analysis - for_each_use/for_each_use_terminator: Iterate over variable uses in instructions - instr_dest: Get destination variable of instructions - set_instr_dest: Redirect instruction output - replace_uses_of: Variable substitution in instructions - count_uses_of: Count how many times a variable is used - is_side_effect_free: Classify instructions **Post-lowering passes** (run after phi node lowering): - empty_blocks: Remove passthrough blocks (only Jump, no instructions) - merge_blocks: Merge single-predecessor blocks with their predecessors - dead_instrs: Remove unused variable definitions - dead_blocks: (refactored) Use shared utils Passes run in multiple iterations to handle cascading opportunities from each pass (e.g., dead_instrs can create empty blocks). The optimize_lowered_ir function coordinates these passes on phi-free IR. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 136373b commit 823406d

6 files changed

Lines changed: 1786 additions & 25 deletions

File tree

crates/herkos-core/src/optimizer/dead_blocks.rs

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,11 @@
44
//! arise naturally during IR translation when code follows an `unreachable` or
55
//! `return` instruction inside a Wasm structured control flow construct.
66
7-
use crate::ir::{BlockId, IrBlock, IrFunction, IrTerminator};
7+
use super::utils::terminator_successors;
8+
use crate::ir::{BlockId, IrBlock, IrFunction};
89
use anyhow::{bail, Result};
910
use std::collections::{HashMap, HashSet};
1011

11-
/// Returns the successor block IDs for a terminator.
12-
fn terminator_successors(term: &IrTerminator) -> Vec<BlockId> {
13-
match term {
14-
IrTerminator::Return { .. } | IrTerminator::Unreachable => vec![],
15-
IrTerminator::Jump { target } => vec![*target],
16-
IrTerminator::BranchIf {
17-
if_true, if_false, ..
18-
} => vec![*if_true, *if_false],
19-
IrTerminator::BranchTable {
20-
targets, default, ..
21-
} => targets
22-
.iter()
23-
.chain(std::iter::once(default))
24-
.copied()
25-
.collect(),
26-
}
27-
}
28-
2912
/// Computes the set of block IDs reachable from the entry block via BFS.
3013
fn reachable_blocks(func: &IrFunction) -> Result<HashSet<BlockId>> {
3114
// Index blocks by ID for O(1) lookup during traversal.
@@ -61,7 +44,7 @@ pub fn eliminate(func: &mut IrFunction) -> Result<()> {
6144
#[cfg(test)]
6245
mod tests {
6346
use super::*;
64-
use crate::ir::{IrInstr, IrValue, TypeIdx, VarId, WasmType};
47+
use crate::ir::{IrInstr, IrTerminator, IrValue, TypeIdx, VarId, WasmType};
6548

6649
/// Build a minimal `IrFunction` with the given blocks.
6750
/// Entry block is always `BlockId(0)`.

0 commit comments

Comments
 (0)