aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-06-07 10:02:56 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-06-07 10:09:12 -0700
commit523ed62b3c68ef4dc04fb2918ae8b1b2f8e2bce1 (patch)
treef57f2e9f26b67009c1b172a96d528085fd5f13cd
parent265dd5a4e28ebd280dafb5febca1b556abc473e8 (diff)
optimize multiple loop variables together
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js45
-rw-r--r--tools/eliminator/asm-eliminator-test.js50
-rw-r--r--tools/js-optimizer.js103
3 files changed, 153 insertions, 45 deletions
diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js
index a7eebe25..52c91ce1 100644
--- a/tools/eliminator/asm-eliminator-test-output.js
+++ b/tools/eliminator/asm-eliminator-test-output.js
@@ -5049,4 +5049,49 @@ function looop7() {
HEAP32[$old_0_i107_i >> 2] = HEAP32[$696 >> 2] | 0;
while (1) {}
}
+function multiloop($n_0, $35) {
+ $n_0 = $n_0 | 0;
+ $35 = $35 | 0;
+ var $p_0 = 0, $41 = 0;
+ $n_0 = $35;
+ $p_0 = (HEAP32[$15 >> 2] | 0) + ($35 << 1) | 0;
+ while (1) {
+ $p_0 = $p_0 - 2 | 0;
+ $41 = HEAPU16[$p_0 >> 1] | 0;
+ if ($41 >>> 0 < $2 >>> 0) {
+ $_off0 = 0;
+ } else {
+ $_off0 = $41 - $2 & 65535;
+ }
+ HEAP16[$p_0 >> 1] = $_off0;
+ $n_0 = $n_0 - 1 | 0;
+ if (($n_0 | 0) == 0) {
+ break;
+ }
+ }
+}
+function multiloop2($n_0, $35) {
+ $n_0 = $n_0 | 0;
+ $35 = $35 | 0;
+ var $p_0 = 0, $39 = 0, $41 = 0, $46 = 0;
+ $n_0 = $35;
+ $p_0 = (HEAP32[$15 >> 2] | 0) + ($35 << 1) | 0;
+ while (1) {
+ $39 = $p_0 - 2 | 0;
+ $41 = HEAPU16[$39 >> 1] | 0;
+ if ($41 >>> 0 < $2 >>> 0) {
+ $_off0 = 0;
+ } else {
+ $_off0 = $41 - $2 & 65535;
+ }
+ HEAP16[$39 >> 1] = $p_0;
+ $46 = $n_0 - 1 | 0;
+ if (($46 | 0) == 0) {
+ break;
+ } else {
+ $n_0 = $46;
+ $p_0 = $39;
+ }
+ }
+}
diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js
index 22b6ddec..e01a89ea 100644
--- a/tools/eliminator/asm-eliminator-test.js
+++ b/tools/eliminator/asm-eliminator-test.js
@@ -6775,5 +6775,53 @@ function looop7() {
while (1) {
}
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7"]
+function multiloop($n_0, $35) {
+ $n_0 = $n_0 | 0;
+ $35 = $35 | 0;
+ var $p_0 = 0, $39 = 0, $41 = 0, $46 = 0;
+ $n_0 = $35;
+ $p_0 = (HEAP32[$15 >> 2] | 0) + ($35 << 1) | 0;
+ while (1) {
+ $39 = $p_0 - 2 | 0;
+ $41 = HEAPU16[$39 >> 1] | 0;
+ if ($41 >>> 0 < $2 >>> 0) {
+ $_off0 = 0;
+ } else {
+ $_off0 = $41 - $2 & 65535;
+ }
+ HEAP16[$39 >> 1] = $_off0;
+ $46 = $n_0 - 1 | 0;
+ if (($46 | 0) == 0) {
+ break;
+ } else {
+ $n_0 = $46;
+ $p_0 = $39;
+ }
+ }
+}
+function multiloop2($n_0, $35) {
+ $n_0 = $n_0 | 0;
+ $35 = $35 | 0;
+ var $p_0 = 0, $39 = 0, $41 = 0, $46 = 0;
+ $n_0 = $35;
+ $p_0 = (HEAP32[$15 >> 2] | 0) + ($35 << 1) | 0;
+ while (1) {
+ $39 = $p_0 - 2 | 0;
+ $41 = HEAPU16[$39 >> 1] | 0;
+ if ($41 >>> 0 < $2 >>> 0) {
+ $_off0 = 0;
+ } else {
+ $_off0 = $41 - $2 & 65535;
+ }
+ HEAP16[$39 >> 1] = $p_0; // cannot optimize one, so none
+ $46 = $n_0 - 1 | 0;
+ if (($46 | 0) == 0) {
+ break;
+ } else {
+ $n_0 = $46;
+ $p_0 = $39;
+ }
+ }
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "__Z11printResultPiS_j", "_segment_holding", "__ZN5identC2EiPKcPci", "_vec2Length", "exc", "label", "confuusion", "tempDouble", "_org_apache_harmony_luni_util_NumberConverter_freeFormat__", "__ZN23b2EdgeAndPolygonContact8EvaluateEP10b2ManifoldRK11b2TransformS4_", "_java_nio_charset_Charset_forNameInternal___java_lang_String", "looop2", "looop3", "looop4", "looop5", "looop6", "looop7", "multiloop", "multiloop2"]
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 2b05aeb3..8e815100 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -2374,57 +2374,72 @@ function eliminate(ast, memSafe) {
ifTrue = temp;
flip = true;
}
- if (ifTrue[1][0][0] == 'break' && !ifTrue[1][1] && ifFalse[1].length == 1 && ifFalse[1][0][0] == 'stat' && ifFalse[1][0][1][0] == 'assign') {
- var assign = ifFalse[1][0][1];
- if (assign[1] === true && assign[2][0] == 'name' && assign[3][0] == 'name') {
- var looper = assign[2][1];
- var helper = assign[3][1];
- if (definitions[helper] == 1 && seenUses[looper] == namings[looper] &&
- !helperReplacements[helper] && !helperReplacements[looper]) {
- // the remaining issue is whether looper is used after the assignment to helper and before the last line (where we assign to it)
- var found = -1;
- for (var i = stats.length-2; i >= 0; i--) {
- var curr = stats[i];
- if (curr[0] == 'stat' && curr[1][0] == 'assign') {
- var currAssign = curr[1];
- if (currAssign[1] === true && currAssign[2][0] == 'name') {
- var to = currAssign[2][1];
- if (to == helper) {
- found = i;
- break;
- }
- }
+ if (ifTrue[1][0][0] == 'break' && !ifTrue[1][1]) {
+ var assigns = ifFalse[1];
+ var loopers = [], helpers = [];
+ for (var i = 0; i < assigns.length; i++) {
+ if (assigns[i][0] == 'stat' && assigns[i][1][0] == 'assign') {
+ var assign = assigns[i][1];
+ if (assign[1] === true && assign[2][0] == 'name' && assign[3][0] == 'name') {
+ var looper = assign[2][1];
+ var helper = assign[3][1];
+ if (definitions[helper] == 1 && seenUses[looper] == namings[looper] &&
+ !helperReplacements[helper] && !helperReplacements[looper]) {
+ loopers.push(looper);
+ helpers.push(helper);
}
}
- if (found >= 0) {
- var looperUsed = false;
- for (var i = found+1; i < stats.length && !looperUsed; i++) {
- var curr = i < stats.length-1 ? stats[i] : last[1]; // on the last line, just look in the condition
- traverse(curr, function(node, type) {
- if (type == 'name' && node[1] == looper) {
- looperUsed = true;
- return true;
- }
- });
- }
- if (!looperUsed) {
- // hurrah! this is safe to do
- varsToRemove[helper] = 2;
- traverse(node, function(node, type) { // replace all appearances of helper with looper
- if (type == 'name' && node[1] == helper) node[1] = looper;
- });
- helperReplacements[helper] = looper; // replace all future appearances of helper with looper
- helperReplacements[looper] = looper; // avoid any further attempts to optimize looper in this manner (seenUses is wrong anyhow, too)
- // simplify the if. we remove the if branch, leaving only the else
- if (flip) {
- last[1] = simplifyNotComps(['unary-prefix', '!', last[1]]);
- last[2] = last[3];
+ }
+ }
+ if (loopers.length < assigns.length) return; // TODO: handle the case where can can just eliminate one. (we can't optimize the break, but we can remove the var at least)
+ for (var l = 0; l < loopers.length; l++) {
+ var looper = loopers[l];
+ var helper = helpers[l];
+ // the remaining issue is whether loopers are used after the assignment to helper and before the last line (where we assign to it)
+ var found = -1;
+ for (var i = stats.length-2; i >= 0; i--) {
+ var curr = stats[i];
+ if (curr[0] == 'stat' && curr[1][0] == 'assign') {
+ var currAssign = curr[1];
+ if (currAssign[1] === true && currAssign[2][0] == 'name') {
+ var to = currAssign[2][1];
+ if (to == helper) {
+ found = i;
+ break;
}
- last.pop();
}
}
}
+ if (found < 0) return;
+ var looperUsed = false;
+ for (var i = found+1; i < stats.length && !looperUsed; i++) {
+ var curr = i < stats.length-1 ? stats[i] : last[1]; // on the last line, just look in the condition
+ traverse(curr, function(node, type) {
+ if (type == 'name' && node[1] == looper) {
+ looperUsed = true;
+ return true;
+ }
+ });
+ }
+ if (looperUsed) return;
+ }
+ // hurrah! this is safe to do
+ for (var l = 0; l < loopers.length; l++) {
+ var looper = loopers[l];
+ var helper = helpers[l];
+ varsToRemove[helper] = 2;
+ traverse(node, function(node, type) { // replace all appearances of helper with looper
+ if (type == 'name' && node[1] == helper) node[1] = looper;
+ });
+ helperReplacements[helper] = looper; // replace all future appearances of helper with looper
+ helperReplacements[looper] = looper; // avoid any further attempts to optimize looper in this manner (seenUses is wrong anyhow, too)
+ }
+ // simplify the if. we remove the if branch, leaving only the else
+ if (flip) {
+ last[1] = simplifyNotComps(['unary-prefix', '!', last[1]]);
+ last[2] = last[3];
}
+ last.pop();
}
}
}