pub mod phase11_string_interning;
pub mod phase12_dead_code_elimination;
pub mod phase13_loop_optimization;
pub mod phase14_escape_analysis;
pub mod phase15_simd_vectorization;
use crate::parser::{Expression, Pattern, Program, Statement};
use typed_arena::Arena;
#[derive(Debug, Clone)]
pub struct OptimizerConfig {
pub enable_string_interning: bool,
pub enable_dead_code_elimination: bool,
pub enable_loop_optimization: bool,
pub enable_escape_analysis: bool,
pub enable_simd_vectorization: bool,
}
impl Default for OptimizerConfig {
fn default() -> Self {
Self {
enable_string_interning: true,
enable_dead_code_elimination: true,
enable_loop_optimization: true,
enable_escape_analysis: false, enable_simd_vectorization: false, }
}
}
#[derive(Debug, Clone)]
pub struct OptimizationResult<'ast> {
pub program: Program<'ast>,
pub stats: OptimizationStats,
}
#[derive(Debug, Clone, Default)]
pub struct OptimizationStats {
pub strings_interned: usize,
pub string_memory_saved: usize,
pub dead_functions_removed: usize,
pub dead_structs_removed: usize,
pub dead_code_bytes_saved: usize,
pub loops_optimized: usize,
pub invariants_hoisted: usize,
pub loops_unrolled: usize,
pub heap_to_stack_conversions: usize,
pub allocations_eliminated: usize,
pub loops_vectorized: usize,
pub simd_speedup_estimate: f64,
}
pub struct Optimizer {
config: OptimizerConfig,
expr_arena: typed_arena::Arena<crate::parser::Expression<'static>>,
stmt_arena: typed_arena::Arena<crate::parser::Statement<'static>>,
pattern_arena: typed_arena::Arena<crate::parser::Pattern<'static>>,
}
impl Optimizer {
pub fn new(config: OptimizerConfig) -> Self {
Self {
config,
expr_arena: Arena::new(),
stmt_arena: Arena::new(),
pattern_arena: Arena::new(),
}
}
pub fn with_defaults() -> Self {
Self::new(OptimizerConfig::default())
}
pub fn alloc_expr<'ast>(&self, expr: Expression<'static>) -> &'ast Expression<'ast> {
unsafe {
let ptr = self.expr_arena.alloc(expr);
std::mem::transmute(ptr)
}
}
pub fn alloc_stmt<'ast>(&self, stmt: Statement<'static>) -> &'ast Statement<'ast> {
unsafe {
let ptr = self.stmt_arena.alloc(stmt);
std::mem::transmute(ptr)
}
}
pub fn alloc_pattern<'ast>(&self, pattern: Pattern<'static>) -> &'ast Pattern<'ast> {
unsafe {
let ptr = self.pattern_arena.alloc(pattern);
std::mem::transmute(ptr)
}
}
pub fn optimize<'ast>(&self, program: &Program<'ast>) -> OptimizationResult<'ast> {
let mut program = program;
let mut stats = OptimizationStats::default();
let mut intermediate_programs: Vec<Program<'ast>> = Vec::new();
if self.config.enable_string_interning {
let result = phase11_string_interning::optimize_string_interning(program, self);
intermediate_programs.push(result.program);
program = intermediate_programs.last().unwrap();
stats.strings_interned = result.strings_interned;
stats.string_memory_saved = result.memory_saved;
}
if self.config.enable_dead_code_elimination {
let (optimized_program, dce_stats) =
phase12_dead_code_elimination::eliminate_dead_code(program, self);
intermediate_programs.push(optimized_program);
program = intermediate_programs.last().unwrap();
stats.dead_functions_removed = dce_stats.unused_functions_removed;
stats.dead_code_bytes_saved =
dce_stats.unreachable_statements_removed + dce_stats.empty_blocks_removed;
}
if self.config.enable_loop_optimization {
let (optimized_program, loop_stats) =
phase13_loop_optimization::optimize_loops(program, self);
intermediate_programs.push(optimized_program);
program = intermediate_programs.last().unwrap();
stats.loops_optimized = loop_stats.loops_optimized;
stats.invariants_hoisted = loop_stats.invariants_hoisted;
stats.loops_unrolled = loop_stats.loops_unrolled;
}
if self.config.enable_escape_analysis {
let (optimized_program, esc_stats) =
phase14_escape_analysis::optimize_escape_analysis(program, self);
intermediate_programs.push(optimized_program);
program = intermediate_programs.last().unwrap();
stats.heap_to_stack_conversions = esc_stats.vectors_stack_allocated
+ esc_stats.strings_inlined
+ esc_stats.boxes_unboxed;
}
if self.config.enable_simd_vectorization {
let (optimized_program, simd_stats) =
phase15_simd_vectorization::optimize_simd_vectorization(program, self);
intermediate_programs.push(optimized_program);
program = intermediate_programs.last().unwrap();
stats.loops_vectorized += simd_stats.loops_vectorized;
}
OptimizationResult {
program: program.clone(),
stats,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_optimizer_creation() {
let optimizer = Optimizer::with_defaults();
assert!(optimizer.config.enable_string_interning);
assert!(optimizer.config.enable_dead_code_elimination);
}
#[test]
fn test_optimizer_custom_config() {
let config = OptimizerConfig {
enable_string_interning: true,
enable_dead_code_elimination: false,
enable_loop_optimization: false,
enable_escape_analysis: false,
enable_simd_vectorization: false,
};
let optimizer = Optimizer::new(config);
assert!(optimizer.config.enable_string_interning);
assert!(!optimizer.config.enable_dead_code_elimination);
}
}