Add switchable optimization config and benchmark framework

WaferConfig: unified config controlling all optimizations individually.
ForthVM::new_with_config(config) to create VMs with custom optimization settings.
All 8 switchable optimizations: peephole, constant_fold, strength_reduce, dce,
tail_call, inline (IR passes) + stack_to_local_promotion (codegen).

Benchmark framework (crates/core/tests/benchmark_report.rs):
- 7 Forth benchmarks: Fibonacci, Factorial, SumRecurse, NestedLoops, GCD, MemFill, Collatz
- Correctness verification across all configs (runs in CI)
- Full report with 128 optimization combinations (cargo test --ignored)
- Measures execution time, compilation time, WASM module bytes
- CONSOLIDATE impact comparison

Key findings from benchmark report:
- Inlining: -77% exec time on Fibonacci, -92% on Collatz
- Stack-to-local promotion: -5.5% WASM module size
- CONSOLIDATE: -72% exec time on Fibonacci (call_indirect -> direct call)
- All optimizations combined: best overall performance
This commit is contained in:
2026-04-02 12:24:57 +02:00
parent 83585d1890
commit 94f6cb6941
6 changed files with 614 additions and 15 deletions
+5 -1
View File
@@ -85,6 +85,8 @@ pub struct CodegenConfig {
pub base_fn_index: u32,
/// Number of functions already in the table.
pub table_size: u32,
/// Enable stack-to-local promotion for straight-line words.
pub stack_to_local_promotion: bool,
}
/// Result of compiling a word to WASM.
@@ -1457,7 +1459,7 @@ pub fn compile_word(
// -- Code section --
// Determine whether to use stack-to-local promotion
let promoted = is_promotable(body);
let promoted = config.stack_to_local_promotion && is_promotable(body);
let scratch_count = count_scratch_locals(body);
let num_locals = if promoted {
let (preload, _) = compute_stack_needs(body);
@@ -1900,6 +1902,7 @@ mod tests {
CodegenConfig {
base_fn_index: 0,
table_size: 16,
stack_to_local_promotion: true,
}
}
@@ -2123,6 +2126,7 @@ mod tests {
let cfg = CodegenConfig {
base_fn_index: 7,
table_size: 16,
stack_to_local_promotion: true,
};
let m = compile_word("t", &[IrOp::PushI32(1)], &cfg).unwrap();
assert_eq!(m.fn_index, 7);