diff options
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/emconfiguren.py | 2 | ||||
-rwxr-xr-x | tools/emmaken.py | 2 | ||||
-rw-r--r-- | tools/js-optimizer.js | 74 | ||||
-rw-r--r-- | tools/shared.py | 16 | ||||
-rw-r--r-- | tools/test-js-optimizer-output.js | 9 | ||||
-rw-r--r-- | tools/test-js-optimizer.js | 7 |
6 files changed, 103 insertions, 7 deletions
diff --git a/tools/emconfiguren.py b/tools/emconfiguren.py index abe41564..d549908b 100755 --- a/tools/emconfiguren.py +++ b/tools/emconfiguren.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +raise Exception('emconfiguren is deprecated!') + ''' This is a helper script for emmaken.py. See docs in that file for more info. ''' diff --git a/tools/emmaken.py b/tools/emmaken.py index a509b940..89785bc5 100755 --- a/tools/emmaken.py +++ b/tools/emmaken.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +raise Exception('emmaken is deprecated!') + ''' emmaken - the emscripten make proxy tool ======================================== diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index d22de39c..bf971951 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -78,6 +78,7 @@ function traverse(node, pre, post, stack) { if (stack) len = stack.length; var result = pre(node, type, stack); if (result == true) return true; + if (typeof result == 'object') node = result; // Continue processing on this node if (stack && len == stack.length) stack.push(0); } for (var i = 0; i < node.length; i++) { @@ -259,8 +260,74 @@ function removeUnneededLabelSettings(ast) { }); } -// Various expression simplifications -function simplifyExpressions(ast) { +// Various expression simplifications. Pre run before closure (where we still have metadata), Post run after. + +function simplifyExpressionsPre(ast) { + // When there is a bunch of math like (((8+5)|0)+12)|0, only the external |0 is needed, one correction is enough. + // At each node, ((X|0)+Y)|0 can be transformed into (X+Y): The inner corrections are not needed + // TODO: Is the same is true for 0xff, 0xffff? + + function simplifyBitops(ast) { + var SAFE_BINARY_OPS = set('+', '-', '*', '/', '%', '|'); + var ZERO = ['num', 0]; + var rerun = true; + while (rerun) { + rerun = false; + traverseGenerated(ast, function(node, type, stack) { + if (type == 'binary' && node[1] == '|' && (jsonCompare(node[2], ZERO) || jsonCompare(node[3], ZERO))) { + stack.push(1); // From here on up, no need for this kind of correction, it's done at the top + + // We might be able to remove this correction + for (var i = stack.length-2; i >= 0; i--) { + if (stack[i] == 1) { + // Great, we can eliminate + rerun = true; + return jsonCompare(node[2], ZERO) ? node[3] : node[2]; + } else if (stack[i] == -1) { + break; // Too bad, we can't + } + } + } else if ((type == 'binary' && node[1] in SAFE_BINARY_OPS) || type == 'num' || type == 'name') { + stack.push(0); // This node is safe in that it does not interfere with this optimization + } else { + stack.push(-1); // This node is dangerous! Give up if you see this before you see '1' + } + }, null, []); + } + } + + // The most common mathop is addition, e.g. in getelementptr done repeatedly. We can join all of those, + // by doing (num+num) ==> newnum, and (name+num)+num = name+newnum + function joinAdditions(ast) { + var rerun = true; + while (rerun) { + rerun = false; + traverseGenerated(ast, function(node, type) { + if (type == 'binary' && node[1] == '+') { + if (node[2][0] == 'num' && node[3][0] == 'num') { + rerun = true; + return ['num', node[2][1] + node[3][1]]; + } + for (var i = 2; i <= 3; i++) { + var ii = 5-i; + for (var j = 2; j <= 3; j++) { + if (node[i][0] == 'num' && node[ii][0] == 'binary' && node[ii][1] == '+' && node[ii][j][0] == 'num') { + rerun = true; + node[ii][j][1] += node[i][1]; + return node[ii]; + } + } + } + } + }); + } + } + + simplifyBitops(ast); + joinAdditions(ast); +} + +function simplifyExpressionsPost(ast) { // We often have branchings that are simplified so one end vanishes, and // we then get // if (!(x < 5)) @@ -373,7 +440,8 @@ var passes = { unGlobalize: unGlobalize, removeAssignsToUndefined: removeAssignsToUndefined, //removeUnneededLabelSettings: removeUnneededLabelSettings, - simplifyExpressions: simplifyExpressions, + simplifyExpressionsPre: simplifyExpressionsPre, + simplifyExpressionsPost: simplifyExpressionsPost, loopOptimizer: loopOptimizer }; diff --git a/tools/shared.py b/tools/shared.py index b61552ba..cecfd4ac 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -28,6 +28,10 @@ DEMANGLER = path_from_root('third_party', 'demangler.py') NAMESPACER = path_from_root('tools', 'namespacer.py') EMCC = path_from_root('emcc') EMXX = path_from_root('em++') +EMAR = path_from_root('emar') +EMLD = path_from_root('emld') +EMRANLIB = path_from_root('emranlib') +EMLIBTOOL = path_from_root('emlibtool') EMMAKEN = path_from_root('tools', 'emmaken.py') AUTODEBUGGER = path_from_root('tools', 'autodebugger.py') DFE = path_from_root('tools', 'dead_function_eliminator.py') @@ -217,7 +221,11 @@ class Building: @staticmethod def get_building_env(): env = os.environ.copy() - env['RANLIB'] = env['AR'] = env['CXX'] = env['CC'] = env['LIBTOOL'] = EMMAKEN + env['CC'] = EMCC + env['CXX'] = EMXX + env['AR'] = EMAR + env['RANLIB'] = EMRANLIB + env['LIBTOOL'] = EMLIBTOOL env['EMMAKEN_COMPILER'] = Building.COMPILER env['EMSCRIPTEN_TOOLS'] = path_from_root('tools') env['CFLAGS'] = env['EMMAKEN_CFLAGS'] = ' '.join(COMPILER_OPTS + Building.COMPILER_TEST_OPTS) # Normal CFLAGS is ignored by some configure's. @@ -369,6 +377,8 @@ class Building: if output_processor is not None: output_processor(open(filename + '.o.js').read()) + return filename + '.o.js' + @staticmethod def pick_llvm_opts(optimization_level, safe=True): ''' @@ -472,6 +482,7 @@ class Building: f = open(filename, 'w') f.write(output) f.close() + return filename @staticmethod def eliminator(filename): @@ -486,6 +497,7 @@ class Building: f = open(filename, 'w') f.write(output) f.close() + return filename @staticmethod def closure_compiler(filename): @@ -502,3 +514,5 @@ class Building: if 'ERROR' in cc_output: raise Exception('Error in cc output: ' + cc_output) + return filename + '.cc.js' + diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js index fcd2380d..d171c5b5 100644 --- a/tools/test-js-optimizer-output.js +++ b/tools/test-js-optimizer-output.js @@ -79,6 +79,11 @@ function ignoreLoopy() { } } function bits() { - print((($s & 65535) + ((($f & 65535) << 16 >> 16) * (($f & 65535) << 16 >> 16) | 0 | 0) % 256 | 0) & 65535); + print((($s & 65535) + (($f & 65535) << 16 >> 16) * (($f & 65535) << 16 >> 16) % 256 | 0) & 65535); } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits"] +function maths() { + check(17); + check(95); + __ZN6b2Vec2C1Ev($this1 + 76 | 0); +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths"] diff --git a/tools/test-js-optimizer.js b/tools/test-js-optimizer.js index e06ebd29..0665462b 100644 --- a/tools/test-js-optimizer.js +++ b/tools/test-js-optimizer.js @@ -83,5 +83,10 @@ function ignoreLoopy() { function bits() { // TODO: optimize this! print((($s & 65535) + ((($f & 65535) << 16 >> 16) * (($f & 65535) << 16 >> 16) | 0 | 0) % 256 | 0) & 65535); } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits"] +function maths() { + check(5+12); + check(90+3+2); + __ZN6b2Vec2C1Ev(((((((($this1 + 20 | 0 | 0) + 8 | 0) + 8 | 0) + 8 | 0) + 8 | 0) + 8 | 0) + 8 | 0) + 8 | 0); +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["abc", "xyz", "xyz2", "expr", "loopy", "bits", "maths"] |