◄ WORLD V · SONNY 5DART 239 · a helldive at the net

THE SCALAR REPLACEMENT a hot array cell becomes a plain scalar

When the same array element is read (and written) many times in a region, every access pays for address arithmetic and a memory touch. Scalar replacement loads the element into a plain scalar once, does all the work on the scalar, and stores back at the end — turning many indexed accesses into one load, some register-speed operations, and one store. It is the bridge from slow aggregate memory to fast scalars, and it depends on proving the element is not aliased or changed by anything else in the region.

THE TECHNIQUE N indexed accesses → 1 load + scalar work + 1 store

An array cell v[i] is used several times. Scalar replacement loads it once into s; the demo counts the indexed loads saved: live demo


HISTORY & CREDIT Callahan, Carr & Kennedy, 1990

“Reading v[i] again is free; it is right there.” — each read is an index computation and a memory access. Pulling the cell into a scalar once turns a sequence of memory touches into register work. The array is convenient; the scalar is fast. cited

1990 · Callahan, Carr & Kennedy — “Improving register allocation for subscripted variables”: scalar replacement of array references driven by dependence analysis.
lineage · Ken Kennedy — the Rice school of memory-hierarchy optimization.
now · scalar replacement plus register allocation is why tight numerical loops keep data out of memory.

The transform is legal exactly when nothing else can touch the cell in the region — no alias, no hidden write. Value semantics give that guarantee for free; pointers make you prove it. Callahan-Carr-Kennedy 1990

RECOMMEND FOR I-13 indexed loads saved, computed

On the canonical compiler, v[2] loaded once into s (=30) and used three times computes the same result (90) with 2 indexed loads saved:

$ i13 run scalar.i13 # v[2] loaded once, used 3x s = 30 r = 90 loads_saved = 2 -- one indexed load instead of three
Recommend: scalar replacement is already idiomatic in I-13 — and safe by construction. Its arrays are value-semantic (a write yields a new array, no aliasing), so reading v[i] into I s <- v[i] and working on s is exactly what the std library already does. The precondition that costs a pointer-language a whole alias analysis — “nothing else touches this cell” — i13 gets from its semantics. The optimization is a coding habit here, not a pass.