aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-03-14 20:05:33 -0700
committerAlon Zakai <alonzakai@gmail.com>2014-03-17 17:56:17 -0700
commit3215f80b20f5cf98390c43a2c5c8b3f4ebcdd984 (patch)
tree28a3c5a52f7a3c07c1b45587f233ffe3b52a6fa1
parent4f0e8c3aed0ce2e4606c5c8facacfbd3c015d375 (diff)
simplifyIfs js optimizer pass
-rwxr-xr-xemcc2
-rw-r--r--tests/test_other.py2
-rw-r--r--tools/js-optimizer.js26
-rw-r--r--tools/test-js-optimizer-si-output.js59
-rw-r--r--tools/test-js-optimizer-si.js73
5 files changed, 160 insertions, 2 deletions
diff --git a/emcc b/emcc
index 1c57d991..3845beb1 100755
--- a/emcc
+++ b/emcc
@@ -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();
+ }
+}
+