Skip to content

comp.ts simplifications: helpers reused, dead code and redundant casts gone (-447 ttok) - #1563

Merged
nicolas-abril merged 3 commits into
mainfrom
simplify-comp-cuts
Oct 14, 2026
Merged

nicolas-abril merged 3 commits into
mainfrom
simplify-comp-cuts

Conversation

@nicolas-abril

@nicolas-abril nicolas-abril commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

This makes room under comp.ts's 64,000 ttok cap for #1438, which adds about 810 ttok. comp.ts goes from 63,968 to 63,521 ttok. It also absorbs #1562. Every change is a plain simplification: no code moves out of the file, and no if is rewritten as an expression.

Compiler (TypeScript)

  • bind_set, ty_adt and ck.tld are used where the code repeated what they do.
  • quant_live and ty_clo fold into their callers (from comp.ts sheds 65 tokens with the same output #1562).
  • seg_new takes its parameters' values instead of words and kinds flattened at each call site.
  • emit_match names its tag test once, as js_match already does.
  • js_call's tail and js_expr's ty0 default to the value most callers pass.
  • F32's intrinsic reuses VIEW, and tag lists are a single string, as one site already did.

C runtime

  • ERR_* is an enum.
  • term_buf folds into term_blk.
  • WL_ARGS takes the count directly and pushes with WL_PUSHN; WL_FRAME and FID_EXIT reuse WL_PUSHN and WL_POPN.
  • A dead show_val prototype, redundant casts and single-use temporaries are gone.

IO layer

  • io_wait's two walks over the parked ring share one io_parked loop.
  • fcntl.h is included once, and IoWork is declared once.

JS runtime

Review fixes (second commit, +135 ttok)

  • emit_clo sets a captured binding's count directly again. bind_set could sink the value and leave bind_pop reading a deleted binding.
  • Tag lists test exact membership through ty_tag instead of a substring test.
  • The IO_EMIT and CLO_APPLY entries take plain words (W64) again.
  • js_expr captures each outer variable once.
  • Metal keeps its own ulong/uint/uchar typedefs.
  • WL_POPN, WL_ARGS and the term bit macros parenthesize their arguments.
  • term_rfc tests RFC_BIT. io_again, io_wait and io_late say "no deadline" plainly instead of through unsigned wraparound.
  • show_val writes fixed text with fputs, not a format string (-Wformat-zero-length on Linux GCC).
  • io_addr names its byte test, and io_push adds a number.

The fixes change no emitted code on the compiler side. The emitted C and JS differ from the first commit only in the runtime lines above, identically across all 772 compiled tests. Building and running every compiled test (C and JS, 5 s each) gives the same pass set on both commits: C 756/772, JS 758/772. The failures are expected-error IO tests that the local harness doesn't model. A ! test's Metal shader builds with --gpu-build, and tsc reports no errors in comp.ts.

Perf fix (third commit, +20 ttok)

  • err_post is a function again. As a macro, combined with the WL_ARGS rewrite, it pushed editdist's SEQ-CPU time from 1.90 s to 2.38 s (1.24x, over the gate's 1.15x limit) and its PAR-CPU time to 1.11x. Neither change slows editdist alone, so this looks like clang laying out the hot loop differently. Bisected locally by applying groups of runtime hunks to main's emitted C.

Gates (minis, at the third commit): repo 54/54, ping 57/57, test 1631/1631, perf 124/124. editdist reads 0.99x on SEQ-CPU and 0.96x on PAR-CPU.

Verification (macOS, M-series)

  • Absorbing comp.ts sheds 65 tokens with the same output #1562 changes no emitted C. The only JS change is cmp_new's line join, the same in all 802 JS outputs.
  • Emitted C and JS are byte-identical to main for all 1,631 tests/*/*.bend wherever only the compiler side changed. Where the runtime text changed, the diffs are exactly the runtime edits.
  • Test runs on the C and JS lanes (rfc, run, reg, base, io, state, eval, halt, stats, show, printer) match main exactly: C 375 pass / 14 fail, JS 399 pass / 20 fail on both. The failures come from my local harness, not from this change.
  • ! programs built and ran on Metal.
  • tsc reports no new errors in comp.ts.
  • Benches (tree-bitonic, hashmap, symreg, raytrace) are within noise of main.
  • Linux (Arch, x86_64, GCC 16, a local port of the test gate that runs shards in bwrap): test passes 1631/1631 at the third commit and on its base. editdist's SEQ-CPU median is within 1% of the base's over 15 interleaved runs. The Linux GCC -Wformat-zero-length concern from the review doesn't reproduce: GCC warns about printf("") but not about the conditional printf(i > 0 ? ", " : ""), so the fputs revert is cleanup only.
  • Not run: CUDA.

🤖 Generated with Claude Code

…s gone (-602 ttok)

- The compiler: bind_set, ty_adt and ck.tld are reused where the code
  repeated them; quant_live and ty_clo fold into their callers; seg_new
  takes its parameters' values; emit_match names its tag test once;
  js_call and js_expr default their usual arguments; F32's intrinsic
  reuses VIEW; tag lists are one string.
- The C runtime: ERR_* is an enum; err_post is a macro on both sides;
  term_buf folds into term_blk; WL_ARGS takes its count directly and
  pushes with WL_PUSHN; Metal uses the stdint typedefs; redundant casts,
  a dead show_val prototype and single-use temporaries go.
- The IO layer: one io_parked walk for io_wait's two loops; fcntl.h is
  included once; IoWork is declared once; strcmp tests read !strcmp.
- The JS runtime: f32_show lets its loop reach inf; io_strerror folds
  into io_fail; io_addr checks a byte with one test; cmp_new is one line.

Absorbs #1562. Emitted C and JS stay byte-identical for every test
where only the compiler changed; the C and JS test runs match main.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nicolas-abril nicolas-abril changed the title comp.ts simplifications: helpers reused, dead code and redundant casts gone (-567 ttok) comp.ts simplifications: helpers reused, dead code and redundant casts gone (-602 ttok) Oct 14, 2026
- emit_clo sets a captured binding's count directly again: bind_set
  could sink it and leave bind_pop reading a deleted binding.
- Tag lists test exact membership through ty_tag, not a substring.
- The IO_EMIT and CLO_APPLY entries take plain words (W64) again.
- js_expr captures each outer variable once.
- Metal keeps its own ulong/uint/uchar typedefs.
- WL_POPN, WL_ARGS and the term bit macros parenthesize again.
- term_rfc tests RFC_BIT; io_again, io_wait and io_late say "no
  deadline" plainly instead of through unsigned wraparound.
- show_val writes fixed text with fputs, not a format string.
- io_addr names its byte test; io_push adds a number.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nicolas-abril nicolas-abril changed the title comp.ts simplifications: helpers reused, dead code and redundant casts gone (-602 ttok) comp.ts simplifications: helpers reused, dead code and redundant casts gone (-467 ttok) Oct 14, 2026
@nicolas-abril nicolas-abril self-assigned this Oct 14, 2026
With err_post a macro, err_fail inlines at every call site, and together
with the WL_ARGS rewrite clang lays the hot loop out worse: editdist went
from 1.90 s to 2.38 s on SEQ-CPU (1.24x, over the gate's 1.15x) and to
1.11x on PAR-CPU. Either change alone is neutral.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@nicolas-abril nicolas-abril changed the title comp.ts simplifications: helpers reused, dead code and redundant casts gone (-467 ttok) comp.ts simplifications: helpers reused, dead code and redundant casts gone (-447 ttok) Oct 14, 2026
@nicolas-abril
nicolas-abril merged commit 014ccd0 into main Oct 14, 2026
1 check passed
@nicolas-abril
nicolas-abril deleted the simplify-comp-cuts branch October 14, 2026 20:58
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