aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-11-09 09:55:18 -0800
committerAlon Zakai <alonzakai@gmail.com>2013-11-09 09:55:18 -0800
commitd420405180ee7910511c6a89572ce9f823880f3a (patch)
treef25b3ae56eafe4085329185e81ee891db73997fe
parent16a5d12dc19b984cf3b55fc2682bd24f1d6834c4 (diff)
Math.* have no side effects
-rw-r--r--tools/eliminator/eliminator-test-output.js3
-rw-r--r--tools/eliminator/eliminator-test.js10
-rw-r--r--tools/js-optimizer.js32
3 files changed, 36 insertions, 9 deletions
diff --git a/tools/eliminator/eliminator-test-output.js b/tools/eliminator/eliminator-test-output.js
index 1a6506ed..0171e99b 100644
--- a/tools/eliminator/eliminator-test-output.js
+++ b/tools/eliminator/eliminator-test-output.js
@@ -6119,4 +6119,7 @@ function intoCond() {
HEAP32[$115 >> 2] = $NumWords;
}
}
+function math(a, b, c, d) {
+ print(Math_imul(d) + (Math_fround(c) + (a + Math_abs(b))));
+}
diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js
index ffad69ea..ef17b388 100644
--- a/tools/eliminator/eliminator-test.js
+++ b/tools/eliminator/eliminator-test.js
@@ -8852,5 +8852,13 @@ function intoCond() {
HEAP32[$504 >> 2] = $503;
}
}
-// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond"]
+function math(a, b, c, d) {
+ var x, y, z, w;
+ x = a;
+ y = Math_abs(b);
+ z = Math_fround(c);
+ w = Math_imul(d);
+ print(x + y + z + w);
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm", "phi", "intoCond", "math"]
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 8b05fc38..d2bfcd91 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -1142,12 +1142,26 @@ function simplifyNotComps(ast) {
simplifyNotCompsPass = false;
}
+function callHasSideEffects(node) { // checks if the call itself (not the args) has side effects (or is not statically known)
+ return !(node[1][0] === 'name' && /^Math_/.test(node[1][1]));
+}
+
function hasSideEffects(node) { // this is 99% incomplete!
switch (node[0]) {
case 'num': case 'name': case 'string': return false;
case 'unary-prefix': return hasSideEffects(node[2]);
case 'binary': return hasSideEffects(node[2]) || hasSideEffects(node[3]);
case 'sub': return hasSideEffects(node[1]) || hasSideEffects(node[2]);
+ case 'call': {
+ if (callHasSideEffects(node)) return true;
+ // This is a statically known call, with no side effects. only args can side effect us
+ var args = node[2];
+ var num = args.length;
+ for (var i = 0; i < num; i++) {
+ if (hasSideEffects(args[i])) return true;
+ }
+ return false;
+ }
default: return true;
}
}
@@ -2445,14 +2459,16 @@ function eliminate(ast, memSafe) {
for (var i = 0; i < args.length; i++) {
traverseInOrder(args[i]);
}
- // these two invalidations will also invalidate calls
- if (!globalsInvalidated) {
- invalidateGlobals();
- globalsInvalidated = true;
- }
- if (!memoryInvalidated) {
- invalidateMemory();
- memoryInvalidated = true;
+ if (callHasSideEffects(node)) {
+ // these two invalidations will also invalidate calls
+ if (!globalsInvalidated) {
+ invalidateGlobals();
+ globalsInvalidated = true;
+ }
+ if (!memoryInvalidated) {
+ invalidateMemory();
+ memoryInvalidated = true;
+ }
}
} else if (type === 'if') {
if (allowTracking) {