diff options
Diffstat (limited to 'tools/js-optimizer.js')
-rw-r--r-- | tools/js-optimizer.js | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index d04807a7..1de06e4c 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -405,13 +405,16 @@ function removeUnneededLabelSettings(ast) { // Various expression simplifications. Pre run before closure (where we still have metadata), Post run after. var USEFUL_BINARY_OPS = set('<<', '>>', '|', '&', '^'); +var COMPARE_OPS = set('<', '<=', '>', '>=', '==', '===', '!='); function simplifyExpressionsPre(ast) { - // Look for (x&A)<<B>>B and replace it with X&A if possible. - function simplifySignExtends(ast) { + // Simplify common expressions used to perform integer conversion operations + // in cases where no conversion is needed. + function simplifyIntegerConversions(ast) { traverse(ast, function(node, type) { if (type === 'binary' && node[1] === '>>' && node[3][0] === 'num' && node[2][0] === 'binary' && node[2][1] === '<<' && node[2][3][0] === 'num' && node[3][1] === node[2][3][1]) { + // Transform (x&A)<<B>>B to X&A. var innerNode = node[2][2]; var shifts = node[3][1]; if (innerNode[0] === 'binary' && innerNode[1] === '&' && innerNode[3][0] === 'num') { @@ -420,6 +423,15 @@ function simplifyExpressionsPre(ast) { return innerNode; } } + } else if (type === 'binary' && node[1] === '&' && node[3][0] === 'num') { + // Rewrite (X < Y) & 1 to (X < Y)|0. (Subsequent passes will eliminate + // the |0 if possible.) + var input = node[2]; + var amount = node[3][1]; + if (input[0] === 'binary' && (input[1] in COMPARE_OPS) && amount == 1) { + node[1] = '|'; + node[3][1] = 0; + } } }); } @@ -763,7 +775,7 @@ function simplifyExpressionsPre(ast) { } traverseGeneratedFunctions(ast, function(func) { - simplifySignExtends(func); + simplifyIntegerConversions(func); simplifyBitops(func); joinAdditions(func); // simplifyZeroComp(func); TODO: investigate performance @@ -2730,8 +2742,9 @@ function relocate(ast) { assert(asm); // we also assume we are normalized var replacements = extraInfo.replacements; - var fBase = extraInfo.fBase; + var fBases = extraInfo.fBases; var hBase = extraInfo.hBase; + var m; traverse(ast, function(node, type) { switch(type) { @@ -2743,13 +2756,14 @@ function relocate(ast) { case 'binary': { if (node[1] == '+' && node[2][0] == 'name') { var base = null; - if (node[2][1] == 'F_BASE') { - base = fBase; - } else if (node[2][1] == 'H_BASE') { + if (node[2][1] == 'H_BASE') { base = hBase; + } else if (m = /^F_BASE_(\w+)$/.exec(node[2][1])) { + base = fBases[m[1]] || 0; // 0 if the parent has no function table for this, but the child does. so no relocation needed } - if (base) { + if (base !== null) { var other = node[3]; + if (base === 0) return other; if (other[0] == 'num') { other[1] += base; return other; @@ -2887,7 +2901,7 @@ arguments_.slice(1).forEach(function(arg) { passes[arg](ast); }); if (asm && last) { - asmLoopOptimizer(ast); + asmLoopOptimizer(ast); // TODO: move out of last, to make last faster when done later (as in side modules) prepDotZero(ast); } var js = astToSrc(ast, minifyWhitespace), old; |