Skip to content

feat: add optimizer infrastructure and post-lowering structural passes#29

Merged
arnoox merged 3 commits intomainfrom
pr-d/optimizer-infrastructure
Mar 23, 2026
Merged

feat: add optimizer infrastructure and post-lowering structural passes#29
arnoox merged 3 commits intomainfrom
pr-d/optimizer-infrastructure

Conversation

@arnoox
Copy link
Owner

@arnoox arnoox commented Mar 23, 2026

Summary

Adds shared optimizer utilities and four post-lowering optimization passes (running after phi node lowering):

  • Shared utilities (optimizer/utils.rs): Basic IR traversal, variable use tracking, instruction classification
  • empty_blocks: Eliminates passthrough blocks (unconditional jumps with no instructions)
  • merge_blocks: Merges single-predecessor blocks with their predecessors
  • dead_instrs: Removes unused variable definitions (when no downstream instruction reads the variable)
  • dead_blocks (refactored): Now uses shared utilities

How it works

Structural passes run in multiple iterations (typically 2) in optimize_lowered_ir() to handle cascading opportunities:

  1. dead_instrs may remove assignments, leaving some blocks empty
  2. empty_blocks and merge_blocks eliminate now-empty/redundant blocks
  3. Repeat until reaching fixed point

Key design notes

  • All new instructions in the codebase (MemoryFill, MemoryInit, DataDrop) are properly handled
  • Passes are independent and can be reordered or disabled
  • This is the foundation for post-lowering passes (PRs E, F add value/loop optimizations on top)

Test coverage

All unit tests pass for:

  • Predecessor map building
  • Use/def tracking
  • Structural transformations
  • Block merging edge cases (loops, diamonds)

🤖 Generated with Claude Code

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>
@arnoox arnoox merged commit 25fef85 into main Mar 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant