Skip typed-array loop versioning in bodies compiled without optimization

Bodies with thousands of capture boxes compile optnone so code generation
stays linear. There a versioned copy only adds code: nothing hoists the
header loads or removes the checks it was made for.
This commit is contained in:
Malte Ubl
2026-10-18 07:48:14 -07:00
parent b7c109dbe1
commit 980036756c
2 changed files with 20 additions and 0 deletions
@@ -258,3 +258,21 @@ test("Float16Array accesses version in elements and share the element tag", () =
// The checked copy keeps its per-element tests.
expect(body.slice(0, body.indexOf(fast))).toContain("bytes.index.invalid");
});
test("bodies compiled without optimization keep one checked loop", () => {
const loop = counted([set(ref("out", f64s), ref("i"), get(ref("src", f64s), ref("i")))]);
const boxes = Array.from({ length: 512 }, (_, k) => local(`box${k}`, F64, true, { boxed: true }));
const mod: IrModule = {
irVersion: 16,
sourceFile: loc.file,
entry: "__main",
functions: [
{ name: "__main", params: [], returnType: VOID, locals: [], body: [], loc },
fn([loop], boxes),
],
};
const body = /^define internal [^\n]*@sc_bf_kernel[^]*?^}/m.exec(emitLlvmModule(mod))![0];
expect(body.split("\n", 1)[0]).toContain("optnone");
expect(body).not.toContain("bytes.version");
expect(body).toContain("bytes.index.invalid");
});
@@ -6995,6 +6995,8 @@ export class LlEmitter {
for (const local of this.currentLocals.values())
if (local.boxed || this.captureIds.has(local.id)) slots.add(`%${mangleLocal(local.id)}`);
B.volatileSlots = slots;
// Without optimization a versioned copy only adds code.
this.bytesLoopVersionsEnabled = false;
}
// Captured bindings come in through the environment — borrowed for the
// whole call (the closure owns them): bound here, never released here.