diff options
| author | 2026-10-14 18:43:45 +0330 | |
|---|---|---|
| committer | 2026-10-14 20:04:08 +0330 | |
| commit | 4c2c7ad06a1132900bf0994a5d8ce492e7f6ae3e (patch) | |
| tree | ac82b4213b73d47c467121069091630939eddb51 | |
| parent | jit_x64_test: a compile error on either core counts as a difference (diff) | |
todo: callee generation guard for direct o3 calls, region 474..692 and fib diagnosis; icon test with an o3 caller across find_replace
| -rw-r--r-- | TODO.md | 2 | ||||
| -rw-r--r-- | tests/icon/regression/o3_caller_replace.expected | 1 | ||||
| -rw-r--r-- | tests/icon/regression/o3_caller_replace.zc | 14 |
3 files changed, 16 insertions, 1 deletions
@@ -546,7 +546,7 @@ brief someone without re-reading the code. ## done in the sorted list - [x] a cross-reference report: for every global of the compiler, the functions that write it and the ones that only read it. build it from the language server's references (`textDocument/references` on `build/bin/zclsp`, so scoping is exact) and classify each reference as a write when an assignment operator, `++` or `--` follows it. output under `build/xref/`; a committed baseline and a `--check` mode that fails when a new writer of a global appears, so it can run in ci. done: `--check` runs in `tests/test.sh` through `xref_selftest.sh` against `tests/xref.baseline`. - [x] x86-64 jit phase 2: compile o3 regions to x86-64 (port `rcompile` and the region register allocation; regions now run on the region interpreter and are 2 to 4 times slower than their plain versions on this jit) and inline enhancements (lower the optimized micro-ops to x86 registers as the arm64 path does, instead of calling `xrun`). validate with `tests/drivers/jit_x64_test.sh` and `tests/bench/bench.sh`, which now has an x86-64 jit column. add the driver to `tests/test.sh` on x86-64 linux. done: inline enhancements merged as 1f4aceb, compiled o3 regions merged as ec49c6d. - done so far: enhancements are inlined (`x64_spec_enh`, `x64_enh`, `x64_uop` in core.c; seven value registers rsi, rdi, r8..r11, rbp; rax, rcx, rdx scratch; floats, byte loads and stores, native calls, popcnt and f2s/s2f still go through `xrun`; `ZYNOENH=1` calls everything as before). bench.sh plain kernels on the x86-64 jit, ms before/after: collatz 49.1/32.1, sieve 4.4/4.1, digits 41.9/14.7, fib 0.83/0.77; o3 unchanged (regions still interpreted). a 256-word pointer sweep with bounds checks 291 to 72 ms. `tests/programs/enh_ops.zc` covers every lowered op on edge values; jit_x64_test runs in test.sh's jit section (not in the quick path). o3 regions now compile (`rjit_x64`, `x64_ralloc`, `remit_x64` in core.c): vars stay in their frame slots, values in six registers, calls go through x_disp; `ZYO3INTERP=1` keeps the region interpreter. bench.sh o3 kernels on the x86-64 jit, ms interpreted/compiled: collatz 289/10.4, sieve 8.7/0.40, digits 89/3.0, fib 3.0/0.92 (fib is still slower than its plain version: calls and returns go through the dispatch stub). still interpreted: regions with more than six live values (one in tests/programs/o3.zc) or native calls. later: vars in registers across a loop, direct o3 calls, floats in xmm registers, spilling instead of giving up. caveat: a store from a region's native code into its own words drops the region, but the block that stored finishes on the old code (arm64 does the same). `-DZYRDUMP` dumps each region's blocks (off by default). the loop-entry flag is done on work/checks (see below). next, after `--explain-checks` v1: direct o3-to-o3 calls on x86-64 (like arm64's `rcall`), so fib stops paying for the dispatch stub. + done so far: enhancements are inlined (`x64_spec_enh`, `x64_enh`, `x64_uop` in core.c; seven value registers rsi, rdi, r8..r11, rbp; rax, rcx, rdx scratch; floats, byte loads and stores, native calls, popcnt and f2s/s2f still go through `xrun`; `ZYNOENH=1` calls everything as before). bench.sh plain kernels on the x86-64 jit, ms before/after: collatz 49.1/32.1, sieve 4.4/4.1, digits 41.9/14.7, fib 0.83/0.77; o3 unchanged (regions still interpreted). a 256-word pointer sweep with bounds checks 291 to 72 ms. `tests/programs/enh_ops.zc` covers every lowered op on edge values; jit_x64_test runs in test.sh's jit section (not in the quick path). o3 regions now compile (`rjit_x64`, `x64_ralloc`, `remit_x64` in core.c): vars stay in their frame slots, values in six registers, calls go through x_disp; `ZYO3INTERP=1` keeps the region interpreter. bench.sh o3 kernels on the x86-64 jit, ms interpreted/compiled: collatz 289/10.4, sieve 8.7/0.40, digits 89/3.0, fib 3.0/0.92 (fib is still slower than its plain version: calls and returns go through the dispatch stub). still interpreted: regions with more than six live values (one in tests/programs/o3.zc) or native calls. later: vars in registers across a loop, direct o3 calls, floats in xmm registers, spilling instead of giving up. caveat: a store from a region's native code into its own words drops the region, but the block that stored finishes on the old code (arm64 does the same). `-DZYRDUMP` dumps each region's blocks (off by default). the loop-entry flag is done on work/checks (see below). next, after `--explain-checks` v1: direct o3-to-o3 calls on x86-64 (like arm64's `rcall`), so fib stops paying for the dispatch stub. a direct o3-to-o3 call must keep a callee generation guard (like llvm's `inline_fn` checking `C->gen`) so a function rewritten by `icon.find_replace` is not bypassed; `tests/icon/regression/o3_caller_replace.zc` calls an o3 callee from an o3 caller before and after a replacement. region 474..692 of tests/programs/o3.zc stays on the region interpreter because it has more than six live values (`x64_ralloc` gives up; needs spilling, dropped from this round, so not a small fix). fib under o3 is slower than plain because each o3 call and return goes through the dispatch stub (`x_disp`) while the plain jit calls directly; the fix is the direct o3 calls above, not small. - [x] llvm by default (decided): llvm is turned on automatically on non-x86-64 hosts; on x86-64 the jit stays the default and llvm is opt-in with `LLVM=1`. - [x] stale known-line check: conformance and parity fail when a known entry passes again (merged in c1072ab). - [x] `defer expr;` and `defer { ... }`: tokens grabbed at the `defer`, recompiled inline at every exit (block end through `block_close`, `return` after its value, `break`/`continue` for entries deeper than the loop), newest first; only defers reached so far register. names are lexical (a local declared after the `defer` is hidden in the replay). a deferred `rt.free(p)` is `p`'s transfer to the analyzer. each entry replays in the analyzer mode it was written in; closures get their own base through `ctx_push`. `return`, `break` and `continue` that would leave a deferred statement are rejected. a failed entry reports once. limit 256 pending per function (`DFR_MAX`). spec 4.14, learn section 34, `tests/programs/defer.zc`, seven reject fixtures. diff --git a/tests/icon/regression/o3_caller_replace.expected b/tests/icon/regression/o3_caller_replace.expected new file mode 100644 index 0000000..91aceec --- /dev/null +++ b/tests/icon/regression/o3_caller_replace.expected @@ -0,0 +1 @@ +21 1 24 diff --git a/tests/icon/regression/o3_caller_replace.zc b/tests/icon/regression/o3_caller_replace.zc new file mode 100644 index 0000000..e55cce2 --- /dev/null +++ b/tests/icon/regression/o3_caller_replace.zc @@ -0,0 +1,14 @@ +include rt; +include run; +include icon; +// an o3 caller must see a published replacement of its callee: a future direct +// o3-to-o3 call has to keep a callee generation guard, not bind the old entry. +o3 int target() { return 7; } +o3 int caller() { int s = 0; for (int i = 0; i < 3; i++) s += target(); return s; } +fn main() { + let seven = run.tokens("7"), eight = run.tokens("8"); + rt.put_n(caller()); rt.put_c(' '); + rt.put_n(icon.find_replace(target, seven, eight)); rt.put_c(' '); + rt.put_n(caller()); rt.put_c(10); + return 0; +} |
