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:
@@ -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;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user