Skip to content

Commit

Permalink
Optimize (x<y)&1
Browse files Browse the repository at this point in the history
Add an optimization to simplifyExpressionsPre to replace (x<y)&1 with x<y
if possible. This comes up frequently in C++ with bool variables.
  • Loading branch information
Dan Gohman committed Jul 2, 2013
1 parent 01708b7 commit 0a2260a
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
18 changes: 15 additions & 3 deletions tools/js-optimizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand All @@ -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;
}
}
});
}
Expand Down Expand Up @@ -763,7 +775,7 @@ function simplifyExpressionsPre(ast) {
}

traverseGeneratedFunctions(ast, function(func) {
simplifySignExtends(func);
simplifyIntegerConversions(func);
simplifyBitops(func);
joinAdditions(func);
// simplifyZeroComp(func); TODO: investigate performance
Expand Down
10 changes: 10 additions & 0 deletions tools/test-js-optimizer-asm-pre-output.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 12 additions & 0 deletions tools/test-js-optimizer-asm-pre.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 0a2260a

Please sign in to comment.