diff options
author | Dan Gohman <sunfish@google.com> | 2013-05-22 14:13:34 -0700 |
---|---|---|
committer | Dan Gohman <sunfish@google.com> | 2013-05-22 14:18:23 -0700 |
commit | c5712288646180f9619e6ef4a58819be64526405 (patch) | |
tree | 1ed3fd72b920e8d17070ce4ac63de218f34e458d | |
parent | 0d4f492e4dc3d02484028e6428c55fab978c7a8b (diff) |
Optimize (x&A)<<B>>B.
Add an optimization to simplifyExpressionsPre to replace (x&A)<<B>>B with X&A
if possible. This comes up frequently in C++ with bool variables.
-rw-r--r-- | tools/js-optimizer.js | 18 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 20 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 14 |
3 files changed, 49 insertions, 3 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 32ed1cce..5e7a2448 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -403,6 +403,23 @@ function removeUnneededLabelSettings(ast) { // Various expression simplifications. Pre run before closure (where we still have metadata), Post run after. function simplifyExpressionsPre(ast) { + // Look for (x&A)<<B>>B and replace it with X&A if possible. + function simplifySignExtends(ast) { + traverseGenerated(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]) { + var innerNode = node[2][2]; + var shifts = node[3][1]; + if (innerNode[0] == 'binary' && innerNode[1] == '&' && innerNode[3][0] == 'num') { + var mask = innerNode[3][1]; + if (mask << shifts >> shifts == mask) { + return innerNode; + } + } + } + }); + } + // When there is a bunch of math like (((8+5)|0)+12)|0, only the external |0 is needed, one correction is enough. // At each node, ((X|0)+Y)|0 can be transformed into (X+Y): The inner corrections are not needed // TODO: Is the same is true for 0xff, 0xffff? @@ -592,6 +609,7 @@ function simplifyExpressionsPre(ast) { }); } + simplifySignExtends(ast); simplifyBitops(ast); joinAdditions(ast); // simplifyZeroComp(ast); TODO: investigate performance diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 72608aa8..ab953e5d 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -18,7 +18,7 @@ function b($this, $__n) { } $4 = $this; $5 = HEAP8[$4 & 16777215] | 0; - if (($5 & 1) << 24 >> 24 == 0) { + if (($5 & 1) == 0) { $14 = 10; $13 = $5; } else { @@ -38,14 +38,14 @@ function b($this, $__n) { } else { $30 = $13; } - if (($30 & 1) << 24 >> 24 == 0) { + if (($30 & 1) == 0) { $38 = $this + 1 | 0; } else { $38 = HEAP32[($this + 8 & 16777215) >> 2] | 0; } _memset($38 + $23 | 0, 0, $__n | 0, 1, 1213141516); $40 = $23 + $__n | 0; - if ((HEAP8[$4 & 16777215] & 1) << 24 >> 24 == 0) { + if ((HEAP8[$4 & 16777215] & 1) == 0) { HEAP8[$4 & 16777215] = $40 << 1 & 255; } else { HEAP32[($this + 4 & 16777215) >> 2] = $40; @@ -93,4 +93,18 @@ function i32_8() { print(5); } } +function sign_extension_simplification() { + if ((HEAP8[$4 & 16777215] & 127) == 0) { + print(5); + } + if ((HEAP8[$4 & 16777215] & 128) << 24 >> 24 == 0) { + print(5); + } + if ((HEAP32[$5 & 16777215] & 32767) == 0) { + print(5); + } + if ((HEAP32[$5 & 16777215] & 32768) << 16 >> 16 == 0) { + print(5); + } +} diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index f2ffaef4..264587d2 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -95,4 +95,18 @@ function i32_8() { print(5); } } +function sign_extension_simplification() { + if ((HEAP8[$4 & 16777215] & 127) << 24 >> 24 == 0) { + print(5); + } + if ((HEAP8[$4 & 16777215] & 128) << 24 >> 24 == 0) { + print(5); + } + if ((HEAP32[$5 & 16777215] & 32767) << 16 >> 16 == 0) { + print(5); + } + if ((HEAP32[$5 & 16777215] & 32768) << 16 >> 16 == 0) { + print(5); + } +} // EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf", "i32_8"] |