diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-03-16 14:00:16 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-03-17 17:56:17 -0700 |
commit | fb331c96b0c710e9b2ff4f944aa4b43e62a320e6 (patch) | |
tree | 46a8bda8e8ce5a678956cf54bbb1c18ab23a8f7a /tools | |
parent | 9b7c27056eccfa8f95dc2c61fe969ab6f353757a (diff) |
fix else fusing when label has multiple assigns or checks
Diffstat (limited to 'tools')
-rw-r--r-- | tools/js-optimizer.js | 37 | ||||
-rw-r--r-- | tools/test-js-optimizer-si-output.js | 57 | ||||
-rw-r--r-- | tools/test-js-optimizer-si.js | 85 |
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"] |