diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-03-14 20:05:33 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-03-17 17:56:17 -0700 |
commit | 3215f80b20f5cf98390c43a2c5c8b3f4ebcdd984 (patch) | |
tree | 28a3c5a52f7a3c07c1b45587f233ffe3b52a6fa1 | |
parent | 4f0e8c3aed0ce2e4606c5c8facacfbd3c015d375 (diff) |
simplifyIfs js optimizer pass
-rwxr-xr-x | emcc | 2 | ||||
-rw-r--r-- | tests/test_other.py | 2 | ||||
-rw-r--r-- | tools/js-optimizer.js | 26 | ||||
-rw-r--r-- | tools/test-js-optimizer-si-output.js | 59 | ||||
-rw-r--r-- | tools/test-js-optimizer-si.js | 73 |
5 files changed, 160 insertions, 2 deletions
@@ -1689,6 +1689,8 @@ try: js_optimizer_queue += ['simplifyExpressions'] + if debug_level == 0 or profiling: js_optimizer_queue += ['simplifyIfs'] + if opt_level >= 3 and shared.Settings.PRECISE_F32: js_optimizer_queue += ['optimizeFrounds'] if closure and not shared.Settings.ASM_JS: diff --git a/tests/test_other.py b/tests/test_other.py index 7200b9fd..a9880cf3 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -1773,6 +1773,8 @@ This pointer might make sense in another type signature: i: 0 ['simplifyExpressions', 'optimizeShiftsConservative']), (path_from_root('tools', 'test-js-optimizer-t2.js'), open(path_from_root('tools', 'test-js-optimizer-t2-output.js')).read(), ['simplifyExpressions', 'optimizeShiftsAggressive']), + (path_from_root('tools', 'test-js-optimizer-si.js'), open(path_from_root('tools', 'test-js-optimizer-si-output.js')).read(), + ['simplifyIfs']), # Make sure that optimizeShifts handles functions with shift statements. (path_from_root('tools', 'test-js-optimizer-t3.js'), open(path_from_root('tools', 'test-js-optimizer-t3-output.js')).read(), ['optimizeShiftsAggressive']), diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 81bf8824..7900044a 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -436,7 +436,7 @@ function removeUnneededLabelSettings(ast) { }); } -// Various expression simplifications. Pre run before closure (where we still have metadata), Post run after. +// Various expression simplifications. Happens after elimination, which opens up many of these simplification opportunities. var USEFUL_BINARY_OPS = set('<<', '>>', '|', '&', '^'); var COMPARE_OPS = set('<', '<=', '>', '>=', '==', '===', '!=', '!=='); @@ -819,11 +819,32 @@ function simplifyExpressions(ast) { simplifyIntegerConversions(func); simplifyBitops(func); joinAdditions(func); - // simplifyZeroComp(func); TODO: investigate performance simplifyNotComps(func); + // simplifyZeroComp(func); TODO: investigate performance }); } + +function simplifyIfs(ast) { + traverse(ast, function(node, type) { + // simplify if (x) { if (y) { .. } } to if (x ? y : 0) { .. } + if (type === 'if' && !node[3]) { + var body = node[2]; + // recurse to handle chains + while (body[0] === 'block' && body[1].length === 1) { + var singleton = body[1][0]; + if (singleton[0] === 'if' && !singleton[3]) { + node[1] = ['conditional', node[1], singleton[1], ['num', 0]]; + body = node[2] = singleton[2]; + } else { + break; + } + } + } + }); +} + + // In typed arrays mode 2, we can have // HEAP[x >> 2] // very often. We can in some cases do the shift on the variable itself when it is set, @@ -5262,6 +5283,7 @@ var passes = { removeAssignsToUndefined: removeAssignsToUndefined, //removeUnneededLabelSettings: removeUnneededLabelSettings, simplifyExpressions: simplifyExpressions, + simplifyIfs: simplifyIfs, optimizeShiftsConservative: optimizeShiftsConservative, optimizeShiftsAggressive: optimizeShiftsAggressive, hoistMultiples: hoistMultiples, diff --git a/tools/test-js-optimizer-si-output.js b/tools/test-js-optimizer-si-output.js new file mode 100644 index 00000000..9a55281d --- /dev/null +++ b/tools/test-js-optimizer-si-output.js @@ -0,0 +1,59 @@ +function a() { + if (x ? y : 0) { + g(); + } + if (x) { + if (y) { + g(); + } else { + h(); + } + } + if (x) { + if (y) { + g(); + } + h(); + } + if (x) { + if (y) { + g(); + } + } else { + h(); + } + if (x) { + f(); + if (y) { + g(); + } + } + if ((x ? y : 0) ? z : 0) { + g(); + } + if (x) { + f(); + if (y ? z : 0) { + g(); + } + } + if (x ? y : 0) { + f(); + if (z) { + g(); + } + } + if (x ? y : 0) { + if (z) { + g(); + } + f(); + } + if (x) { + if (y ? z : 0) { + g(); + } + f(); + } +} + diff --git a/tools/test-js-optimizer-si.js b/tools/test-js-optimizer-si.js new file mode 100644 index 00000000..1d214386 --- /dev/null +++ b/tools/test-js-optimizer-si.js @@ -0,0 +1,73 @@ +function a() { + if (x) { + if (y) { + g(); + } + } + if (x) { + if (y) { + g(); + } else { + h(); + } + } + if (x) { + if (y) { + g(); + } + h(); + } + if (x) { + if (y) { + g(); + } + } else { + h(); + } + if (x) { + f(); + if (y) { + g(); + } + } + if (x) { + if (y) { + if (z) { + g(); + } + } + } + if (x) { + f(); + if (y) { + if (z) { + g(); + } + } + } + if (x) { + if (y) { + f(); + if (z) { + g(); + } + } + } + if (x) { + if (y) { + if (z) { + g(); + } + f(); + } + } + if (x) { + if (y) { + if (z) { + g(); + } + } + f(); + } +} + |