Skip to content

Commit ccfd4da

Browse files
authored
Simplify getFastValue function. NFC (#18680)
This function used to go all kinds of fancy stuff, but today we only ever use it for addition.
1 parent 7f008b9 commit ccfd4da

File tree

1 file changed

+28
-91
lines changed

1 file changed

+28
-91
lines changed

src/parseTools.js

Lines changed: 28 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -191,22 +191,6 @@ function isPointerType(type) {
191191
return type[type.length - 1] == '*';
192192
}
193193

194-
function isIntImplemented(type) {
195-
return type[0] == 'i' || type[0] == 'u' || isPointerType(type);
196-
}
197-
198-
// Note: works for iX types and structure types, not pointers (even though they are implemented as ints)
199-
function getBits(type, allowPointers) {
200-
if (allowPointers && isPointerType(type)) return POINTER_SIZE;
201-
if (!type) return 0;
202-
if (type[0] == 'i' || type[0] == 'u') {
203-
const left = type.substr(1);
204-
if (!isNumber(left)) return 0;
205-
return parseInt(left);
206-
}
207-
return 0;
208-
}
209-
210194
// Given an expression like (VALUE=VALUE*2,VALUE<10?VALUE:t+1) , this will
211195
// replace VALUE with value. If value is not a simple identifier of a variable,
212196
// value will be replaced with tempVar.
@@ -405,12 +389,13 @@ function makeHEAPView(which, start, end) {
405389
return `HEAP${which}.subarray((${start})${mod}, (${end})${mod})`;
406390
}
407391

408-
const TWO_TWENTY = Math.pow(2, 20);
409-
410392
// Given two values and an operation, returns the result of that operation.
411393
// Tries to do as much as possible at compile time.
412-
// Leaves overflows etc. unhandled, *except* for integer multiply, in order to be efficient with Math.imul
413-
function getFastValue(a, op, b, type) {
394+
function getFastValue(a, op, b) {
395+
// In the past we supported many operations, but today we only use addition.
396+
assert(op == '+');
397+
398+
// Convert 'true' and 'false' to '1' and '0'.
414399
a = a === 'true' ? '1' : (a === 'false' ? '0' : a);
415400
b = b === 'true' ? '1' : (b === 'false' ? '0' : b);
416401

@@ -419,95 +404,47 @@ function getFastValue(a, op, b, type) {
419404
if (typeof a == 'number') {
420405
aNumber = a;
421406
a = a.toString();
422-
} else if (isNumber(a)) aNumber = parseFloat(a);
407+
} else if (isNumber(a)) {
408+
aNumber = parseFloat(a);
409+
}
423410
if (typeof b == 'number') {
424411
bNumber = b;
425412
b = b.toString();
426-
} else if (isNumber(b)) bNumber = parseFloat(b);
413+
} else if (isNumber(b)) {
414+
bNumber = parseFloat(b);
415+
}
427416

417+
// First check if we can do the addition at compile time
428418
if (aNumber !== null && bNumber !== null) {
429-
switch (op) {
430-
case '+': return (aNumber + bNumber).toString();
431-
case '-': return (aNumber - bNumber).toString();
432-
case '*': return (aNumber * bNumber).toString();
433-
case '/': {
434-
if (type[0] === 'i') {
435-
return ((aNumber / bNumber) | 0).toString();
436-
}
437-
return (aNumber / bNumber).toString();
438-
}
439-
case '%': return (aNumber % bNumber).toString();
440-
case '|': return (aNumber | bNumber).toString();
441-
case '>>>': return (aNumber >>> bNumber).toString();
442-
case '&': return (aNumber & bNumber).toString();
443-
case 'pow': return Math.pow(aNumber, bNumber).toString();
444-
default: assert(false, 'need to implement getFastValue pn ' + op);
445-
}
419+
return (aNumber + bNumber).toString();
446420
}
447-
if (op === 'pow') {
448-
if (a === '2' && isIntImplemented(type)) {
449-
return `(1 << (${b}))`;
450-
}
451-
return `Math.pow(${a}, ${b})`;
452-
}
453-
if ((op === '+' || op === '*') && aNumber !== null) { // if one of them is a number, keep it last
421+
422+
// If one of them is a number, keep it last
423+
if (aNumber !== null) {
454424
const c = b;
455425
b = a;
456426
a = c;
457427
const cNumber = bNumber;
458428
bNumber = aNumber;
459429
aNumber = cNumber;
460430
}
461-
if (op === '*') {
462-
// We can't eliminate where a or b are 0 as that would break things for creating
463-
// a negative 0.
464-
if ((aNumber === 0 || bNumber === 0) && !FLOAT_TYPES.has(type)) {
465-
return '0';
466-
} else if (aNumber === 1) {
467-
return b;
468-
} else if (bNumber === 1) {
469-
return a;
470-
} else if (bNumber !== null && type && isIntImplemented(type) && Runtime.getNativeTypeSize(type) <= 32) {
471-
const shifts = Math.log(bNumber) / Math.LN2;
472-
if (shifts % 1 === 0) {
473-
return `(${a}<<${shifts})`;
474-
}
475-
}
476-
if (!FLOAT_TYPES.has(type)) {
477-
// if guaranteed small enough to not overflow into a double, do a normal multiply
478-
// default is 32-bit multiply for things like getelementptr indexes
479-
const bits = getBits(type) || 32;
480-
// Note that we can emit simple multiple in non-asm.js mode, but asm.js
481-
// will not parse "16-bit" multiple, so must do imul there
482-
if ((aNumber !== null && Math.abs(a) < TWO_TWENTY) || (bNumber !== null && Math.abs(b) < TWO_TWENTY)) {
483-
// keep a non-eliminatable coercion directly on this
484-
return `(((${a})*(${b}))&${(Math.pow(2, bits) - 1) | 0})`;
485-
}
486-
return `(Math.imul(${a}, ${b})|0)`;
487-
}
488-
} else if (op === '/') {
489-
// careful on floats, since 0*NaN is not 0
490-
if (a === '0' && !FLOAT_TYPES.has(type)) {
491-
return '0';
492-
} else if (b === 1) {
493-
return a;
494-
} // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky
495-
} else if (op === '+' || op === '-') {
496-
if (b[0] === '-') {
497-
op = op === '+' ? '-' : '+';
498-
b = b.substr(1);
499-
}
500-
if (aNumber === 0) {
501-
return op === '+' ? b : `(-${b})`;
502-
} else if (bNumber === 0) {
503-
return a;
504-
}
431+
432+
if (aNumber === 0) {
433+
return b;
434+
} else if (bNumber === 0) {
435+
return a;
505436
}
437+
438+
if (b[0] === '-') {
439+
op = '-'
440+
b = b.substr(1);
441+
}
442+
506443
return `(${a})${op}(${b})`;
507444
}
508445

509446
function calcFastOffset(ptr, pos) {
510-
return getFastValue(ptr, '+', pos, 'i32');
447+
return getFastValue(ptr, '+', pos);
511448
}
512449

513450
function getHeapForType(type) {

0 commit comments

Comments
 (0)