Problem
Walking a function's instructions from .lg IR-pipeline code forces allocations that a hot loop cannot avoid: ir/block-insts hands back a (possibly lazy) sequence, and predicate-style walks (some + closure) allocate a closure per block. The :try contribution-model refactor (op-catalog workflow, #268) measured the cost directly: consolidating the scattered function-needs-error? / function-needs-rt? conditionals into per-op contribution predicates costs +20.9% (bytecode) / +11.6% (gogen_ir) allocs/op on BenchmarkIRCompile, with no zero-alloc expression available at the call sites. Alternatives tested: loop/recur variant was worse (+69%); the closure form is the local minimum under the current API.
Captain decision (2026-07-31): the regression is accepted conditionally — the consolidation lands now, and this improved IR API is the follow-up that recovers the cost. Until it exists, the workflow's performance-metrics requirement (bench-ratchet at par) remains the standing gate for further IR-pipeline work.
What this issue asks for
An inst-iteration surface the IR pipeline can use without per-block/per-call allocation:
- Eager inst access (indexed vector or preallocated array view) or an iterator that does not realize lazy seqs per block.
- A walk/fold primitive that takes a named top-level fn (no closure capture) or is specialized at lowering time.
- Longer-term alignment with the ops-as-types direction: contribution facets as native catalog properties with direct dispatch, so whole-function property folds are table lookups, not interpreted predicate calls.
Acceptance
BenchmarkIRCompile allocs/op for the contribution-model code path returns to (or below) the pre-refactor baseline, with the consolidation retained.
Related: #268 (op catalog — where the cost was taken), #464 (runtime performance epic), #663 (performance measurement status).
Problem
Walking a function's instructions from
.lgIR-pipeline code forces allocations that a hot loop cannot avoid:ir/block-instshands back a (possibly lazy) sequence, and predicate-style walks (some+ closure) allocate a closure per block. The:trycontribution-model refactor (op-catalog workflow, #268) measured the cost directly: consolidating the scatteredfunction-needs-error?/function-needs-rt?conditionals into per-op contribution predicates costs +20.9% (bytecode) / +11.6% (gogen_ir) allocs/op on BenchmarkIRCompile, with no zero-alloc expression available at the call sites. Alternatives tested: loop/recur variant was worse (+69%); the closure form is the local minimum under the current API.Captain decision (2026-07-31): the regression is accepted conditionally — the consolidation lands now, and this improved IR API is the follow-up that recovers the cost. Until it exists, the workflow's performance-metrics requirement (bench-ratchet at par) remains the standing gate for further IR-pipeline work.
What this issue asks for
An inst-iteration surface the IR pipeline can use without per-block/per-call allocation:
Acceptance
BenchmarkIRCompile allocs/op for the contribution-model code path returns to (or below) the pre-refactor baseline, with the consolidation retained.
Related: #268 (op catalog — where the cost was taken), #464 (runtime performance epic), #663 (performance measurement status).