Archive — history, not state. Kept for its reasoning and its evidence; its plan is closed.
Wide integral literal correctness
Status: retained correctness repair; final integrated campaign validation is green. This does not claim a performance win.
Finding
Pit source numbers are parsed as host numeric values. The compiler previously
used mathematical is_integer as if it meant “fits the PitValue tagged-int
lane.” That is false for finite integral literals outside signed int32. For
example, 2147483648 was typed as int; native QBE lowering emitted
2147483648 * 2 as though it were a tagged int, and Mach converted the double
to int32_t before checking whether the conversion preserved the value. The
two targets could therefore turn a valid number into an unrelated tagged value.
This is correctness work, not a benchmark optimization.
Decision and implementation
pit-compiler/numeric_literals.cm now separates two target-neutral questions:
is_wholeimplements the language predicate: every finite mathematical integer remains an integer even when stored in the floating lane;fits_int_laneclassifies signed values from-2147483648through2147483647for current immediate representation and optimizer facts;- every other numeric literal uses the floating numeric lane without changing
its language-level
is_integerresult.
Parser semantic tags, whole-program resolution, mcode slot typing, streamline,
LICM, switch recognition, integer ranges, the IR verifier, linked pure-leaf
fact repair, and QBE lowering consume the same lane-fit predicate. Semantic
folding, array-key classification, and switch recognition use is_whole.
Native access
materializes a wide integral literal with qbe_new_float64; it no longer
constructs an invalid tagged-int bit pattern. Mach checks the double against
the int32 range before any C integer conversion and otherwise adds it to the
float constant pool. Mach’s ordinary and fused is_int operations and native
QBE lowering now use the whole-number predicate, while Pit_IsInt remains a
low-level C representation-tag test. Fused array guards preserve the semantic
predicate result and separately require an immediate/range-safe index before
using trusted array helpers.
The nan64 profile preserves the exact finite values used by the regression. The existing 64-bit f32 profile still uses the same int32 tagged lane; a wide literal therefore takes its float32 lane and rounds with the profile’s existing rules. No representation arithmetic or public language semantics changed.
The planned true 32-bit playdate-nan32 profile has a narrower signed immediate
lane. Its representation seam must supply that profile-specific limit rather
than copying int32 comparisons into new passes. The shared predicate makes the
remaining migration point explicit, but this correction does not implement
nan32.
Tests and cost
The focused compiler regression covers 2147483648, -2147483649, and
3000000001, checks final slot types and QBE IL, then executes comparisons,
arithmetic, and remainder under Mach. The same source is registered in the
dual-lane benchmark harness with an exact golden result, so Mach and native
cannot merely agree on the same wrong answer.
Focused validation after the implementation seed rebuild:
- compiler tests: 141 passed, 0 failed;
- dual-lane regression: Mach
127, native127, golden checkY; - regression census: 79 Mach instructions, 24 native observer instructions, about 1 KiB allocated in either lane, 0 collections.
The later integrated gate passed make seed, 145/145 focused compiler checks,
1,086/1,086 isolated VM checks, 1,921/1,921 warmed full-suite checks, and
3,733/3,733 deterministic fuzz checks over 500 programs. The dual-lane golden
regression remained part of the final 68-row aggregate, where every row
returned check=Y.
The audit also exposed a pre-existing constant-fold bug: fold.cm used the
coarse number type tag to fold is_integer(wide_whole) to false. Literal
folding now consults is_whole; the regression separately exercises folded
and generic retained-is_int forms.
Ordinary int32 literals generate the same mcode and target code as before. There is no runtime metadata, frame, record, heap, or executable memory cost. Only programs containing a wide integral literal change code: they now pay the same constant materialization cost as an explicitly fractional float literal, which is required for correctness.
Source: plans/archive/perf-2026-07/perf-wide-integral-literals.md