From 774886bb37a49c56f9aa579e444b6bdb9d90d264 Mon Sep 17 00:00:00 2001 From: Brummel Date: Sun, 10 May 2026 12:31:37 +0200 Subject: [PATCH] design-md-consolidation 2.4: condense Decision 11 mono-vs-vdisp correction history to state-only rationale --- docs/DESIGN.md | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index f6d7171..03b742c 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -1520,22 +1520,18 @@ After this pass, the IR contains no class machinery — only ordinary monomorphic functions and direct calls. Codegen sees no difference between a hand-written `show_int` and a synthesised `show__Int`. -**Why mono, not virtual dispatch (the empirically-grounded version).** -The original rationale implicitly argued that mono saves a per-call -indirect-jump cost. A mono-vs-vdisp micro-benchmark -(`bench/mono_dispatch.py`, JOURNAL bench-notes entry) refutes -that specific claim: on a saturating branch predictor with a -monomorphic indirect target, indirect dispatch is free relative to -the same-shape non-inlined direct call. -The correct rationale is one level up: **mono makes the call target -visible to the optimiser, unlocking inlining and downstream loop -transformations that virtual dispatch prevents in principle.** The -measured end-to-end win on a tight LCG hot loop is substantial vs -non-inlinable direct call and larger still vs polymorphic vdisp (4 distinct -targets cycling). On larger callee bodies or cold call sites the -inlining win shrinks toward zero, but the architectural claim — "mono -enables optimisations vdisp forbids" — holds across the spectrum, -while the older "saves an indirect call" framing does not. +**Why mono, not virtual dispatch.** Monomorphisation makes the call +target visible to the optimiser, unlocking inlining and downstream +loop transformations that virtual dispatch prevents in principle. +On a saturating branch predictor with a monomorphic indirect +target, the indirect call itself is comparable in cost to a +non-inlined direct call — the win is in what the optimiser can do +with the visible target, not in the call instruction. The +end-to-end gain shrinks toward zero on larger callee bodies and +cold call sites, but the architectural claim — "mono enables +optimisations vdisp forbids" — holds across the spectrum +(`bench/mono_dispatch.py` and the corresponding JOURNAL bench-notes +entry record the measured ratios). The separator is `__` rather than `#` or `@` because `#` and `@` are invalid in LLVM IR global identifiers (the IR verifier rejects