aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Gohman <sunfish@google.com>2013-05-22 14:13:34 -0700
committerDan Gohman <sunfish@google.com>2013-05-22 14:18:23 -0700
commitc5712288646180f9619e6ef4a58819be64526405 (patch)
tree1ed3fd72b920e8d17070ce4ac63de218f34e458d
parent0d4f492e4dc3d02484028e6428c55fab978c7a8b (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.js18
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js20
-rw-r--r--tools/test-js-optimizer-asm-pre.js14
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"]