aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-11-29 11:33:31 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-12-07 14:23:19 -0800
commit1b591a0b0c8d330dafdac65e732c6f14c22a19ca (patch)
tree30503b8737686ee756f681a9cf367640cdcef9b4
parentb707c2c64149107db7906e1ef442dc25a3224276 (diff)
add eliminator mode for asm
-rwxr-xr-xemcc7
-rwxr-xr-xtests/runner.py2
-rw-r--r--tools/eliminator/asm-eliminator-test-output.js8
-rw-r--r--tools/eliminator/asm-eliminator-test.js11
-rw-r--r--tools/eliminator/eliminator-test.js2
-rw-r--r--tools/js-optimizer.js12
6 files changed, 37 insertions, 5 deletions
diff --git a/emcc b/emcc
index 4102ebf0..eface9b7 100755
--- a/emcc
+++ b/emcc
@@ -1166,7 +1166,12 @@ try:
if DEBUG: save_intermediate('pretty')
def get_eliminate():
- return 'eliminate' if not shared.Settings.ALLOW_MEMORY_GROWTH else 'eliminateMemSafe'
+ if shared.Settings.ASM_JS:
+ return 'eliminateAsm'
+ elif shared.Settings.ALLOW_MEMORY_GROWTH:
+ return 'eliminateMemSafe'
+ else:
+ return 'eliminate'
js_optimizer_queue += [get_eliminate()]
diff --git a/tests/runner.py b/tests/runner.py
index cb0c8bdb..163779d5 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -8531,6 +8531,8 @@ f.close()
['eliminate']),
(path_from_root('tools', 'eliminator', 'safe-eliminator-test.js'), open(path_from_root('tools', 'eliminator', 'safe-eliminator-test-output.js')).read(),
['eliminateMemSafe']),
+ (path_from_root('tools', 'eliminator', 'asm-eliminator-test.js'), open(path_from_root('tools', 'eliminator', 'asm-eliminator-test-output.js')).read(),
+ ['eliminateAsm']),
]:
output = Popen([NODE_JS, path_from_root('tools', 'js-optimizer.js'), input] + passes, stdin=PIPE, stdout=PIPE).communicate()[0]
self.assertIdentical(expected, output.replace('\r\n', '\n').replace('\n\n', '\n'))
diff --git a/tools/eliminator/asm-eliminator-test-output.js b/tools/eliminator/asm-eliminator-test-output.js
new file mode 100644
index 00000000..228915d4
--- /dev/null
+++ b/tools/eliminator/asm-eliminator-test-output.js
@@ -0,0 +1,8 @@
+function asm(x, y) {
+ x = +x;
+ y = y | 0;
+ var a = 0;
+ a = cheez(y + ~~x | 0) | 0;
+ fleefl(a * a | 0, a | 0);
+}
+
diff --git a/tools/eliminator/asm-eliminator-test.js b/tools/eliminator/asm-eliminator-test.js
new file mode 100644
index 00000000..d845b989
--- /dev/null
+++ b/tools/eliminator/asm-eliminator-test.js
@@ -0,0 +1,11 @@
+function asm(x, y) {
+ x = +x;
+ y = y|0;
+ var a = 0, b = +0, c = 0;
+ var label = 0;
+ a = cheez((y+~~x)|0)|0;
+ b = a*a;
+ fleefl(b|0, a|0);
+}
+// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "c", "f", "g", "h", "py", "r", "t", "f2", "f3", "llvm3_1", "_inflate", "_malloc", "_mallocNoU", "asm"]
+
diff --git a/tools/eliminator/eliminator-test.js b/tools/eliminator/eliminator-test.js
index d7982130..07a41d71 100644
--- a/tools/eliminator/eliminator-test.js
+++ b/tools/eliminator/eliminator-test.js
@@ -8828,7 +8828,7 @@ function _mallocNoU($bytes) {
return $mem_0;
return null;
}
-function asm(x, y) {
+function asm(x, y) { // asm-style code, without special asm requested so will not be fully optimized
x = +x;
y = y|0;
var a = 0, b = +0, c = 0;
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index 29aecdcf..53d1bb31 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -1408,7 +1408,7 @@ var NODES_WITHOUT_ELIMINATION_SIDE_EFFECTS = set('name', 'num', 'string', 'binar
var IGNORABLE_ELIMINATOR_SCAN_NODES = set('num', 'toplevel', 'string', 'break', 'continue', 'dot'); // dot can only be STRING_TABLE.*
var ABORTING_ELIMINATOR_SCAN_NODES = set('new', 'object', 'function', 'defun', 'switch', 'for', 'while', 'array', 'throw'); // we could handle some of these, TODO, but nontrivial (e.g. for while, the condition is hit multiple times after the body)
-function eliminate(ast, memSafe) {
+function eliminate(ast, memSafe, asm) {
// Find variables that have a single use, and if they can be eliminated, do so
traverseGeneratedFunctions(ast, function(func, type) {
//printErr('eliminate in ' + func[1]);
@@ -1426,6 +1426,7 @@ function eliminate(ast, memSafe) {
locals[func[2][i]] = true;
}
}
+ var defaultDefs = asm ? -1 : 0; // in asm.js we have an extra formal def which we can ignore
// examine body and note locals
traverse(func, function(node, type) {
if (type === 'var') {
@@ -1435,7 +1436,7 @@ function eliminate(ast, memSafe) {
var name = node1i[0];
var value = node1i[1];
if (value) {
- if (!definitions[name]) definitions[name] = 0;
+ if (!(name in definitions)) definitions[name] = defaultDefs;
definitions[name]++;
if (!values[name]) values[name] = value;
}
@@ -1450,7 +1451,7 @@ function eliminate(ast, memSafe) {
var target = node[2];
if (target[0] == 'name') {
var name = target[1];
- if (!definitions[name]) definitions[name] = 0;
+ if (!(name in definitions)) definitions[name] = defaultDefs;
definitions[name]++;
if (!uses[name]) uses[name] = 0;
if (!values[name]) values[name] = node[3];
@@ -1872,6 +1873,10 @@ function eliminateMemSafe(ast) {
eliminate(ast, true);
}
+function eliminateAsm(ast) {
+ eliminate(ast, false, true);
+}
+
// Passes table
var compress = false, printMetadata = true;
@@ -1891,6 +1896,7 @@ var passes = {
registerize: registerize,
eliminate: eliminate,
eliminateMemSafe: eliminateMemSafe,
+ eliminateAsm: eliminateAsm,
compress: function() { compress = true; },
noPrintMetadata: function() { printMetadata = false; }
};