Merge pull request #839 from vercel-labs/perf/length-to-double-nneg

Convert lengths and in-range indices to doubles as non-negative
This commit is contained in:
Chris Tate
2026-10-10 21:27:14 -05:00
committed by GitHub
9 changed files with 21 additions and 21 deletions
@@ -213,7 +213,7 @@ test("length assignments skip the runtime when the length is unchanged", () => {
module("reset", VOID, [{ kind: "arraySetLength", arr: ref("s", words), length: index, loc }]),
);
const fn = body(llvm, "reset");
expect(fn).toMatch(/uitofp i64 .* to double/);
expect(fn).toMatch(/uitofp nneg i64 .* to double/);
expect(fn).toMatch(/fcmp oeq double %p?\S*, %t\d+/);
expect(fn.match(/call void @scr_arr_set_len\(/g)).toHaveLength(1);
expect(fn).toMatch(/br i1 %t\d+, label %arr\.len\.done\d*, label %arr\.len\.set\d*/);
@@ -411,7 +411,7 @@ export function emitDenseArrayPush(
fastValue = B.tmp();
B.line(`${next} = add nuw ${size} ${len}, 1`);
B.line(`store ${size} ${next}, ptr ${lenPtr}${host.fieldAliasAttachment(lenPtr)}`);
B.line(`${fastValue} = uitofp ${size} ${next} to double`);
B.line(`${fastValue} = uitofp nneg ${size} ${next} to double`);
B.br(join);
B.startBlock(slow);
const slowValue = B.tmp();
+5 -5
View File
@@ -1668,7 +1668,7 @@ export class LlDyn {
host.declare(`declare void @scr_arr_set_len(ptr, double)`);
const index = B.tmp();
const length = B.tmp();
B.line(`${index} = uitofp ${this.S} ${i} to double`);
B.line(`${index} = uitofp nneg ${this.S} ${i} to double`);
B.line(`${length} = fadd double ${index}, 1.0`);
B.line(`call void @scr_arr_set_len(ptr ${a}, double ${length})`);
B.br(doneLabel);
@@ -3409,7 +3409,7 @@ export class LlDyn {
const n = this.lenOf(B, "%d");
const nd = B.tmp();
const r = B.tmp();
B.line(`${nd} = uitofp ${host.sizeType} ${n} to double`);
B.line(`${nd} = uitofp nneg ${host.sizeType} ${n} to double`);
B.line(`${r} = call ptr @scr_dyn_new_num(double ${nd})`);
B.terminate(`ret ptr ${r}`);
B.startBlock(lStr);
@@ -3448,7 +3448,7 @@ export class LlDyn {
const n2 = B.tmp();
B.line(`${n2} = call double @scr_str_utf16_len(ptr ${s})`);
const idxD = B.tmp();
B.line(`${idxD} = uitofp ${host.sizeType} ${idx} to double`);
B.line(`${idxD} = uitofp nneg ${host.sizeType} ${idx} to double`);
const inR2 = B.tmp();
B.line(`${inR2} = fcmp olt double ${idxD}, ${n2}`);
const lHit2 = B.newLabel("kg.ash");
@@ -3599,7 +3599,7 @@ export class LlDyn {
host.declare(`declare ptr @scr_dyn_jsval_iter_n(ptr, double)`);
const count = B.tmp();
const out = B.tmp();
B.line(`${count} = uitofp ${host.sizeType} %n to double`);
B.line(`${count} = uitofp nneg ${host.sizeType} %n to double`);
B.line(`${out} = call ptr @scr_dyn_jsval_iter_n(ptr %d, double ${count})`);
B.terminate(`ret ptr ${out}`);
B.startBlock(lNotJv);
@@ -3737,7 +3737,7 @@ export class LlDyn {
const index = B.tmp();
const bd = B.tmp();
const r = B.tmp();
B.line(`${index} = uitofp ${host.sizeType} ${i} to double`);
B.line(`${index} = uitofp nneg ${host.sizeType} ${i} to double`);
B.line(`${bd} = call double @scr_bytes_get(ptr ${bts}, double ${index})`);
B.line(`${r} = call ptr @scr_dyn_new_num(double ${bd})`);
B.line(`store ptr ${r}, ptr ${itemSlot}`);
@@ -1925,7 +1925,7 @@ export class LlEmitter {
// The branch must dominate fptoui: NaN/out-of-range conversion
// would produce poison. Fractional indices also need a fallback.
` %index = fptoui double %i to ${this.sizeType}`,
` %roundtrip = uitofp ${this.sizeType} %index to double`,
` %roundtrip = uitofp nneg ${this.sizeType} %index to double`,
` %integer = fcmp oeq double %roundtrip, %i`,
` br i1 %integer, label %read, label %fallback`,
`read:`,
@@ -2759,14 +2759,14 @@ export class LlEmitter {
`entry:`,
` %ndp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 19`,
` %nd = load ${sz}, ptr %ndp`,
` %ndf = uitofp ${sz} %nd to double`,
` %ndf = uitofp nneg ${sz} %nd to double`,
` %lo = fcmp oge double %k, 0.0`,
` %hi = fcmp olt double %k, %ndf`,
` %in = and i1 %lo, %hi`,
` br i1 %in, label %direct, label %outside`,
`direct:`,
` %i = fptoui double %k to ${sz}`,
` %back = uitofp ${sz} %i to double`,
` %back = uitofp nneg ${sz} %i to double`,
` %int = fcmp oeq double %back, %k`,
` br i1 %int, label %slot, label %miss`,
`slot:`,
@@ -5626,7 +5626,7 @@ export class LlEmitter {
B.line(`${lenPtr} = getelementptr inbounds %ScrArr, ptr ${arr.name}, i32 0, i32 1`);
this.markMemoryPointer(lenPtr, "array:header");
B.line(`${len} = load ${this.sizeType}, ptr ${lenPtr}${this.fieldAliasAttachment(lenPtr)}`);
B.line(`${lenNumber} = uitofp ${this.sizeType} ${len} to double`);
B.line(`${lenNumber} = uitofp nneg ${this.sizeType} ${len} to double`);
B.line(`${same} = fcmp oeq double ${length.name}, ${lenNumber}`);
B.condBr(same, done, resize);
B.startBlock(resize);
@@ -6255,7 +6255,7 @@ export class LlEmitter {
B.line(
`${rawLen} = load ${this.sizeType}, ptr ${lenPtr}${this.fieldAliasAttachment(lenPtr)}`,
);
B.line(`${len} = uitofp ${this.sizeType} ${rawLen} to double`);
B.line(`${len} = uitofp nneg ${this.sizeType} ${rawLen} to double`);
B.line(`${inBounds} = fcmp olt double ${i}, ${len}`);
cur = i;
}
@@ -122,7 +122,7 @@ export function emitBytesIndex(
const nonnegative = B.tmp();
const belowLen = B.tmp();
const inRange = B.tmp();
B.line(`${lenF64} = uitofp ${host.sizeType} ${len} to double`);
B.line(`${lenF64} = uitofp nneg ${host.sizeType} ${len} to double`);
B.line(`${nonnegative} = fcmp oge double ${index}, ${f64Lit(0)}`);
B.line(`${belowLen} = fcmp olt double ${index}, ${lenF64}`);
B.line(`${inRange} = and i1 ${nonnegative}, ${belowLen}`);
@@ -137,7 +137,7 @@ export function emitBytesIndex(
const roundTrip = B.tmp();
const integral = B.tmp();
B.line(`${idx} = fptoui double ${index} to ${host.sizeType}`);
B.line(`${roundTrip} = uitofp ${host.sizeType} ${idx} to double`);
B.line(`${roundTrip} = uitofp nneg ${host.sizeType} ${idx} to double`);
B.line(`${integral} = fcmp oeq double ${roundTrip}, ${index}`);
B.condBr(integral, valid, invalid);
@@ -177,7 +177,7 @@ export function emitBytesLength(
const count = bytes && size !== 1 ? B.tmp() : len;
if (count !== len) B.line(`${count} = shl ${host.sizeType} ${len}, ${Math.log2(size)}`);
const out = B.tmp();
B.line(`${out} = uitofp ${host.sizeType} ${count} to double`);
B.line(`${out} = uitofp nneg ${host.sizeType} ${count} to double`);
return { name: out, type: F64 };
}
@@ -520,7 +520,7 @@ export function emitArrIntrinsic(
B.line(`${p} = getelementptr inbounds %ScrArr, ptr ${r.name}, i32 0, i32 1`);
host.markMemoryPointer(p, "array:header");
B.line(`${len} = load ${host.sizeType}, ptr ${p}${host.fieldAliasAttachment(p)}`);
B.line(`${t} = uitofp ${host.sizeType} ${len} to double`);
B.line(`${t} = uitofp nneg ${host.sizeType} ${len} to double`);
return { name: t, type: e.type };
}
case "getNumber": {
@@ -348,7 +348,7 @@ function emitDenseReferenceArrayRead(
B.line(`${cap} = load ${host.sizeType}, ptr ${capPtr}${host.fieldAliasAttachment(capPtr)}`);
if (integerIndex) B.line(`${inRange} = icmp ult ${host.sizeType} ${integerIndex}, ${cap}`);
else {
B.line(`${capNumber} = uitofp ${host.sizeType} ${cap} to double`);
B.line(`${capNumber} = uitofp nneg ${host.sizeType} ${cap} to double`);
B.line(`${nonnegative} = fcmp oge double ${index.name}, 0.0`);
B.line(`${belowCap} = fcmp olt double ${index.name}, ${capNumber}`);
B.line(`${inRange} = and i1 ${nonnegative}, ${belowCap}`);
@@ -361,7 +361,7 @@ function emitDenseReferenceArrayRead(
if (integerIndex) B.br(dense);
else {
B.line(`${offset} = fptoui double ${index.name} to ${host.sizeType}`);
B.line(`${roundTrip} = uitofp ${host.sizeType} ${offset} to double`);
B.line(`${roundTrip} = uitofp nneg ${host.sizeType} ${offset} to double`);
B.line(`${integral} = fcmp oeq double ${index.name}, ${roundTrip}`);
B.condBr(integral, dense, slow);
}
@@ -45,7 +45,7 @@ export const STRING_READ_HELPERS: readonly StringReadHelper[] = [
` br i1 %ascii, label %fast, label %slow`,
`fast:`,
...loadLength(sz),
` %n = uitofp ${sz} %len to double`,
` %n = uitofp nneg ${sz} %len to double`,
` ret double %n`,
`slow:`,
` %r = call double @scr_str_utf16_len(ptr %s)`,
@@ -62,7 +62,7 @@ export const STRING_READ_HELPERS: readonly StringReadHelper[] = [
` br i1 %ascii, label %bounds, label %slow`,
`bounds:`,
...loadLength(sz),
` %lenf = uitofp ${sz} %len to double`,
` %lenf = uitofp nneg ${sz} %len to double`,
// NaN fails both ordered comparisons; -0 passes and truncates to 0.
` %lo = fcmp oge double %i, 0.0`,
` %hi = fcmp olt double %i, %lenf`,
@@ -97,7 +97,7 @@ export function emitStringSliceRead(host: LlvmEmitterContext, value: Slice): LlV
`${pointer} = getelementptr inbounds { ${host.sizeType}, ${host.sizeType}, i32 }, ptr ${snapshot.range}, i32 0, i32 1`,
);
B.line(`${length} = load ${host.sizeType}, ptr ${pointer}`);
B.line(`${number} = uitofp ${host.sizeType} ${length} to double`);
B.line(`${number} = uitofp nneg ${host.sizeType} ${length} to double`);
return { name: number, type: value.type };
}
if (value.method !== "charCodeAt") return null;