Add stack-to-local promotion, verify all optimizations end-to-end

Stack-to-local promotion (Phase 1):
- is_promotable() identifies straight-line words (no control flow/calls/I/O)
- StackSim maps stack slots to WASM locals
- Stack manipulation (Swap, Rot, Nip, Tuck, Dup, Drop) emits ZERO instructions
- Prologue loads items from memory, epilogue writes back
- ~7x instruction reduction for DUP * and similar patterns

End-to-end verification (16 tests proving each optimization is active):
- verify_peephole_active: 0+ elimination
- verify_constant_folding_active: 3 4 + folded to 7
- verify_strength_reduction_active: 4* becomes shift
- verify_dce_active: code after EXIT eliminated
- verify_tail_call_active: recursive RECURSE works
- verify_inlining_active: small word inlined and folded
- verify_compound_ops_active: 2DUP works
- verify_dsp_caching_active: factorial via RECURSE
- verify_consolidation_active: CONSOLIDATE word
- verify_stack_promotion_*: 7 tests for promoted codegen

22 additional codegen promotion tests (wasmtime execution).
Fix F~ stack overflow panic (checked_sub instead of unchecked).
380 unit tests + 11 compliance tests, all passing.
This commit is contained in:
2026-04-01 23:51:15 +02:00
parent 08885b4589
commit 83585d1890
3 changed files with 895 additions and 19 deletions
+19 -15
View File
@@ -415,17 +415,19 @@ fn inline(ops: Vec<IrOp>, bodies: &HashMap<WordId, Vec<IrOp>>, max_size: usize)
match &op {
IrOp::Call(id) => {
if let Some(body) = bodies.get(id)
&& body.len() <= max_size && !contains_call_to(body, *id) {
// Inline the body, converting TailCall back to Call
// (tail position in the callee is not tail position in the caller)
for inlined_op in body {
match inlined_op {
IrOp::TailCall(tid) => out.push(IrOp::Call(*tid)),
other => out.push(other.clone()),
}
&& body.len() <= max_size
&& !contains_call_to(body, *id)
{
// Inline the body, converting TailCall back to Call
// (tail position in the callee is not tail position in the caller)
for inlined_op in body {
match inlined_op {
IrOp::TailCall(tid) => out.push(IrOp::Call(*tid)),
other => out.push(other.clone()),
}
continue;
}
continue;
}
out.push(op);
}
_ => {
@@ -451,9 +453,10 @@ fn contains_call_to(ops: &[IrOp], target: WordId) -> bool {
return true;
}
if let Some(eb) = else_body
&& contains_call_to(eb, target) {
return true;
}
&& contains_call_to(eb, target)
{
return true;
}
}
IrOp::DoLoop { body, .. } | IrOp::BeginUntil { body } | IrOp::BeginAgain { body } => {
if contains_call_to(body, target) {
@@ -480,9 +483,10 @@ fn contains_call_to(ops: &[IrOp], target: WordId) -> bool {
return true;
}
if let Some(eb) = else_body
&& contains_call_to(eb, target) {
return true;
}
&& contains_call_to(eb, target)
{
return true;
}
}
_ => {}
}