diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-06-07 10:02:56 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-06-07 10:09:12 -0700 |
commit | 523ed62b3c68ef4dc04fb2918ae8b1b2f8e2bce1 (patch) | |
tree | f57f2e9f26b67009c1b172a96d528085fd5f13cd | |
parent | 265dd5a4e28ebd280dafb5febca1b556abc473e8 (diff) |
optimize multiple loop variables together
-rw-r--r-- | tools/eliminator/asm-eliminator-test-output.js | 45 | ||||
-rw-r--r-- | tools/eliminator/asm-eliminator-test.js | 50 | ||||
-rw-r--r-- | tools/js-optimizer.js | 103 |
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(); } } } |