diff options
-rw-r--r-- | tools/js-optimizer.js | 18 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 10 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 12 |
3 files changed, 37 insertions, 3 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index d04807a7..85171a02 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 diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 301a2ec8..59a42010 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -119,6 +119,16 @@ function sign_extension_simplification() { print(5); } } +function compare_result_simplification() { + HEAP32[$4] = HEAP32[$5] < HEAP32[$6]; + HEAP32[$4] = HEAP32[$5] > HEAP32[$6]; + HEAP32[$4] = HEAP32[$5] <= HEAP32[$6]; + HEAP32[$4] = HEAP32[$5] <= HEAP32[$6]; + HEAP32[$4] = HEAP32[$5] == HEAP32[$6]; + HEAP32[$4] = HEAP32[$5] === HEAP32[$6]; + HEAP32[$4] = HEAP32[$5] != HEAP32[$6]; + var x = HEAP32[$5] != HEAP32[$6] | 0; +} function tempDoublePtr($45, $14, $28, $42) { $45 = $45 | 0; $14 = $14 | 0; diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index c7c92124..7ca941fa 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -122,6 +122,18 @@ function sign_extension_simplification() { print(5); } } +function compare_result_simplification() { + // Eliminate these '&1's. + HEAP32[$4] = (HEAP32[$5] < HEAP32[$6]) & 1; + HEAP32[$4] = (HEAP32[$5] > HEAP32[$6]) & 1; + HEAP32[$4] = (HEAP32[$5] <= HEAP32[$6]) & 1; + HEAP32[$4] = (HEAP32[$5] <= HEAP32[$6]) & 1; + HEAP32[$4] = (HEAP32[$5] == HEAP32[$6]) & 1; + HEAP32[$4] = (HEAP32[$5] === HEAP32[$6]) & 1; + HEAP32[$4] = (HEAP32[$5] != HEAP32[$6]) & 1; + // Convert the &1 to |0 here, since we don't get an implicit coersion. + var x = (HEAP32[$5] != HEAP32[$6]) & 1; +} function tempDoublePtr($45, $14, $28, $42) { $45 = $45 | 0; $14 = $14 | 0; |