Skip to content

bugc: add function inlining pass (L2)#252

Merged
gnidan merged 1 commit into
mainfrom
compiler-inlining-pass
Jul 13, 2026
Merged

bugc: add function inlining pass (L2)#252
gnidan merged 1 commit into
mainfrom
compiler-inlining-pass

Conversation

@gnidan

@gnidan gnidan commented Jul 13, 2026

Copy link
Copy Markdown
Member

Adds a function-inlining optimization at level 2. InliningStep
replaces calls to eligible internal functions with a copy of the
callee's body spliced into the caller, eliminating the runtime
JUMP and frame setup for those calls.

v1 eligibility, favoring correctness over coverage:

  • internal, non-recursive, single-return leaf callees;
  • applied at every call site; a callee whose sites are all inlined
    is deleted;
  • self-recursive / tail-call-optimized callers are left untouched.
    Inlining a helper into a tail-recursive call's arguments
    (count(succ(n))count(n + 1)) would rewrite the tail call
    into a computed-argument form the tail-call optimizer mishandles,
    so recursive callers are skipped.

Inlining runs first at L2 (after L1 constant folding, before
CSE/TCO/jump-opt) so the later passes still apply to inlined code.
Return values use dest-substitution rather than a continuation phi,
so they survive L3 block-merging. Inlined instructions retain their
callee source mapping.

Deferred to follow-ups: non-leaf/nested callees, multi-return, and
size-threshold (non-leaf) inlining.

Tests: a new inlining.test.ts covers runtime equivalence at O0–O3,
callee deletion / call elimination at L2, and the recursive-caller
guard. optimizer-contexts.test.ts is updated for the new L2+
behavior (leaf helpers no longer produce a real caller JUMP).

Adds InliningStep at optimization level 2: it replaces calls to
eligible internal functions with a copy of the callee's body
spliced into the caller, eliminating the runtime JUMP/frame.

v1 eligibility (correctness over coverage):
- internal, non-recursive, single-return LEAF callees;
- applied at all call sites; a fully-inlined callee is deleted;
- self-recursive / tail-call-optimized callers are left untouched
  — inlining a helper into a tail-recursive call's arguments
  (count(succ(n)) -> count(n + 1)) rewrites the tail call into a
  form the tail-call optimizer mishandles.

Inlining runs first at L2 (after L1 constant folding, before
CSE/TCO/jump-opt) so those passes still apply to inlined code.
Return values use dest-substitution (not a continuation phi), so
they survive L3 block-merging. Inlined instructions keep their
callee source mapping.

Deferred: non-leaf/nested callees, multi-return, size-threshold
inlining.
@github-actions

github-actions Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-13 04:31 UTC

@gnidan gnidan merged commit 0b8342d into main Jul 13, 2026
4 checks passed
@gnidan gnidan deleted the compiler-inlining-pass branch July 13, 2026 04:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant