aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-03-16 14:00:16 -0700
committerAlon Zakai <alonzakai@gmail.com>2014-03-17 17:56:17 -0700
commitfb331c96b0c710e9b2ff4f944aa4b43e62a320e6 (patch)
tree46a8bda8e8ce5a678956cf54bbb1c18ab23a8f7a /tools
parent9b7c27056eccfa8f95dc2c61fe969ab6f353757a (diff)
fix else fusing when label has multiple assigns or checks
Diffstat (limited to 'tools')
-rw-r--r--tools/js-optimizer.js37
-rw-r--r--tools/test-js-optimizer-si-output.js57
-rw-r--r--tools/test-js-optimizer-si.js85
3 files changed, 164 insertions, 15 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index c38b51d5..1c3bc8c0 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -879,6 +879,41 @@ function simplifyIfs(ast) {
if (simplifiedAnElse) {
// there may be fusing opportunities
+
+ // we can only fuse if we remove all uses of the label. if there are
+ // other ones - if the label check can be reached from elsewhere -
+ // we must leave it
+ var abort = false;
+
+ var labelAssigns = {};
+ traverse(func, function(node, type) {
+ if (type === 'assign' && node[2][0] === 'name' && node[2][1] === 'label') {
+ if (node[3][0] === 'num') {
+ var value = node[3][1];
+ labelAssigns[value] = (labelAssigns[value] || 0) + 1;
+ } else {
+ // label is assigned a dynamic value (like from indirectbr), we cannot do anything
+ abort = true;
+ }
+ }
+ });
+ if (abort) return;
+
+ var labelChecks = {};
+ traverse(func, function(node, type) {
+ if (type === 'binary' && node[1] === '==' && node[2][0] === 'binary' && node[2][1] === '|' &&
+ node[2][2][0] === 'name' && node[2][2][1] === 'label') {
+ if (node[3][0] === 'num') {
+ var value = node[3][1];
+ labelChecks[value] = (labelChecks[value] || 0) + 1;
+ } else {
+ // label is checked vs a dynamic value (like from indirectbr), we cannot do anything
+ abort = true;
+ }
+ }
+ });
+ if (abort) return;
+
traverse(func, function(node, type) {
var stats = getStatements(node);
if (stats) {
@@ -894,7 +929,7 @@ function simplifyIfs(ast) {
postCond[3][0] === 'num') {
var postValue = postCond[3][1];
var preElse = pre[3];
- if (preElse[0] === 'block' && preElse[1] && preElse[1].length === 1) {
+ if (labelAssigns[postValue] === 1 && labelChecks[postValue] === 1 && preElse[0] === 'block' && preElse[1] && preElse[1].length === 1) {
var preStat = preElse[1][0];
if (preStat[0] === 'stat' && preStat[1][0] === 'assign' &&
preStat[1][1] === true && preStat[1][2][0] === 'name' && preStat[1][2][1] === 'label' &&
diff --git a/tools/test-js-optimizer-si-output.js b/tools/test-js-optimizer-si-output.js
index a6e8f53e..0a2468b5 100644
--- a/tools/test-js-optimizer-si-output.js
+++ b/tools/test-js-optimizer-si-output.js
@@ -112,18 +112,27 @@ function a() {
if (x ? y : 0) {
f();
} else {
- label = 5;
+ label = 52;
}
- if ((label | 0) == 6) {
+ if ((label | 0) == 62) {
label = 0;
a();
}
if (x ? y : 0) {
f();
} else {
- label = 5;
+ label = 53;
}
- if ((label | 0) == 5) {
+ if ((label | 0) == 53) {
+ a();
+ }
+ if (x ? y : 0) {
+ label = 54;
+ } else {
+ label = 54;
+ }
+ if ((label | 0) == 54) {
+ label = 0;
a();
}
}
@@ -138,4 +147,44 @@ function b() {
a();
}
}
+function c() {
+ label = x;
+ if (x ? y : 0) {
+ f();
+ } else {
+ label = 151;
+ }
+ if ((label | 0) == 151) {
+ label = 0;
+ a();
+ }
+}
+function d() {
+ if (x ? y : 0) {
+ f();
+ } else {
+ label = 251;
+ }
+ if ((label | 0) == 251) {
+ label = 0;
+ a();
+ }
+ if ((label | 0) == 251) {
+ a();
+ }
+}
+function e() {
+ if (x ? y : 0) {
+ f();
+ } else {
+ label = 351;
+ }
+ if ((label | 0) == 351) {
+ label = 0;
+ a();
+ }
+ if ((label | 0) == x) {
+ a();
+ }
+}
diff --git a/tools/test-js-optimizer-si.js b/tools/test-js-optimizer-si.js
index 78683d6c..9bb82da4 100644
--- a/tools/test-js-optimizer-si.js
+++ b/tools/test-js-optimizer-si.js
@@ -130,12 +130,12 @@ function a() {
if (y) {
f();
} else {
- label = 5;
+ label = 51;
}
} else {
- label = 5;
+ label = 51;
}
- if ((label|0) == 5) {
+ if ((label|0) == 51) {
label = 0;
a();
}
@@ -143,12 +143,12 @@ function a() {
if (y) {
f();
} else {
- label = 5;
+ label = 52;
}
} else {
- label = 5;
+ label = 52;
}
- if ((label|0) == 6) {
+ if ((label|0) == 62) {
label = 0;
a();
}
@@ -156,12 +156,25 @@ function a() {
if (y) {
f();
} else {
- label = 5;
+ label = 53;
}
} else {
- label = 5;
+ label = 53;
}
- if ((label|0) == 5) {
+ if ((label|0) == 53) {
+ a();
+ }
+ if (x) {
+ if (y) {
+ label = 54; // extra label setting, cannot fuse here
+ } else {
+ label = 54;
+ }
+ } else {
+ label = 54;
+ }
+ if ((label|0) == 54) {
+ label = 0;
a();
}
}
@@ -176,4 +189,56 @@ function b() {
a();
}
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b"]
+function c() {
+ label = x; // dynamic assign to label, suppresses label removal
+ if (x) {
+ if (y) {
+ f();
+ } else {
+ label = 151;
+ }
+ } else {
+ label = 151;
+ }
+ if ((label|0) == 151) {
+ label = 0;
+ a();
+ }
+}
+function d() {
+ if (x) {
+ if (y) {
+ f();
+ } else {
+ label = 251;
+ }
+ } else {
+ label = 251;
+ }
+ if ((label|0) == 251) {
+ label = 0;
+ a();
+ }
+ if ((label|0) == 251) { // extra check of label, suppresses label removal
+ a();
+ }
+}
+function e() {
+ if (x) {
+ if (y) {
+ f();
+ } else {
+ label = 351;
+ }
+ } else {
+ label = 351;
+ }
+ if ((label|0) == 351) {
+ label = 0;
+ a();
+ }
+ if ((label|0) == x) { // dynamic check of label, suppresses label removal
+ a();
+ }
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "d"]