diff options
| author | 2026-10-12 08:46:23 +0330 | |
|---|---|---|
| committer | 2026-10-12 08:46:23 +0330 | |
| commit | ecc350ca5c2eb50be8309c5f14f8bf0d87db9a02 (patch) | |
| tree | 70e0af76a1b13affff7c6cc8aac7b3e6ef960478 /docs/history/39-blocks | |
a
Diffstat (limited to 'docs/history/39-blocks')
| -rw-r--r-- | docs/history/39-blocks/notes.md | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/docs/history/39-blocks/notes.md b/docs/history/39-blocks/notes.md new file mode 100644 index 0000000..5133381 --- /dev/null +++ b/docs/history/39-blocks/notes.md @@ -0,0 +1,43 @@ +# 39 — blocks + +a `for` left the lifter as a test, an empty jump, a body and a step. the raw sieve's inner loop was four dispatches per flag. after the blocks exist and before any backend runs, three cleanups share one cfg. + +an empty jump (no ops, no stack, no variable write) is retargeted at its successor, including an entry that landed on it. a jump to a block that has no other predecessor, and that is not itself an entry, is pasted onto that predecessor: the two stacks are empty, and a read of a variable the first half already wrote uses that value. a header whose test is a branch, and whose one edge is a straight run of those jumps back to the header, is rotated. the run plus a copy of the test becomes one block. the zero edge of that test still leaves, and the other edge branches to the block itself. the header's first test stays in front of it, so a loop that runs zero times never enters. a body that contains another branch is left alone, which is the inner sieve's bounds check and the `if (f[i])` around it. a block nothing can reach becomes a jump to itself, so it is not a second predecessor of the live loop. + +the raw sieve's fill, its inner `j += i` store, and its count are each one block per iteration. the checked sieve's fill and count are too. its inner loop is the test, the bounds branch, and one block that stores and steps. the same blocks are what the interpreter, the arm64 jit and llvm compile. the fixpoint is still 109545 words. this pass is in the core, and the genome did not change. the suite is 438 passed, 0 failed: interpreter, microcore, soft-float, the small and run-only maps, both virt boards, the arm64 jit and llvm. + +## sieve + +milliseconds per count, median of five slopes. the before column is `history/38-bounds`. plain bytecode is the control: this pass only reshapes o3 regions. + +| path | before | after | +| --- | ---: | ---: | +| gcc -O3 -march=native, word flags | 0.148 | 0.167 | +| gcc -O3 -march=native -flto, byte flags | 0.080 | 0.080 | +| zc interpreter, plain, bounds-checked | 144.2 | 144.1 | +| zc interpreter, o3, bounds-checked | 18.42 | 12.46 | +| zc interpreter, o3, raw pointer | 14.22 | 7.97 | +| zc llvm, ZYHOT=1, o3 raw pointer | 0.254 | 0.227 | +| zc llvm, ZYHOT=1, o3 bounds-checked | 0.430 | 0.414 | +| zc arm64 jit, qemu-user, o3 raw pointer | 2.080 | 1.931 | + +the interpreter's raw pointer went from 14.22 ms to 7.97 ms, and the checked o3 sieve from 18.42 ms to 12.46 ms. the arm64 jit went from 2.080 ms to 1.931 ms. gcc's word flags came out at 0.167 ms on this run, against 0.148 ms last time, and the byte flags stayed at 0.080 ms. the plain zc sieve, which is still bytecode, stayed at 144 ms. + +`bench/run.sh` timed the llvm raw pointer at 315 repetitions. one of the five trials came out negative, and the median of that set is 0.399 ms (spread -0.72 to 0.88). a slope from 4000 repetitions to 16000 on the same binary is 0.227 ms (0.224 to 0.238), and that is the after column. the checked sieve's long slope is 0.439 ms (0.430 to 0.483), next to the run's 0.414 ms. the inner checked loop still branches on the bounds test, so llvm did not get a single block there, and the raw pointer stayed near a quarter of a millisecond rather than the byte-flag 0.080 ms. + +## trees + +milliseconds per tree of depth 12. gcc on this run was 0.091 for malloc and 0.0144 for the arena. these kernels are calls and recursion. a straight counted loop is not where they spend the time. + +| path | before | after | +| --- | ---: | ---: | +| gcc -O3 -march=native, malloc | 0.091 | 0.091 | +| gcc -O3 -march=native -flto, arena | 0.0143 | 0.0144 | +| zc interpreter, plain new/free | 72.73 | 75.69 | +| zc interpreter, o3 new/free | 162.0 | 158.6 | +| zc interpreter, o3 arena | 1.429 | 1.413 | +| zc llvm, ZYHOT=1, plain new/free | 7.32 | 7.58 | +| zc llvm, ZYHOT=1, o3 new/free | 18.31 | 17.68 | +| zc llvm, ZYHOT=1, o3 arena | 0.184 | 0.159 | +| zc arm64 jit, qemu-user, plain new/free | 44.21 | 44.87 | +| zc arm64 jit, qemu-user, o3 arena | 0.838 | 0.836 | |
