aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-03-26 17:42:39 -0700
committerAlon Zakai <alonzakai@gmail.com>2014-03-27 13:50:01 -0700
commit14d6b2cdab8e48deddb2b114c47406bcb1796b3a (patch)
tree0d3e45899feba230080399b83641d881c37555fd
parent9ce739dbabb00ce0391c3790253fa686edb0a006 (diff)
remove stack parameter from js optimizer traverse(), to avoid overhead when not needed
-rw-r--r--tests/test_other.py9
-rw-r--r--tools/js-optimizer.js447
-rw-r--r--tools/test-js-optimizer-output.js78
-rw-r--r--tools/test-js-optimizer-t2-output.js91
-rw-r--r--tools/test-js-optimizer-t2.js92
-rw-r--r--tools/test-js-optimizer-t2c-output.js17
-rw-r--r--tools/test-js-optimizer-t2c.js18
-rw-r--r--tools/test-js-optimizer-t3-output.js49
-rw-r--r--tools/test-js-optimizer-t3.js50
9 files changed, 59 insertions, 792 deletions
diff --git a/tests/test_other.py b/tests/test_other.py
index 60bdefe1..8c6a199c 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -1774,16 +1774,9 @@ This pointer might make sense in another type signature: i: 0
def test_js_optimizer(self):
for input, expected, passes in [
(path_from_root('tools', 'test-js-optimizer.js'), open(path_from_root('tools', 'test-js-optimizer-output.js')).read(),
- ['hoistMultiples', 'loopOptimizer', 'removeAssignsToUndefined', 'simplifyExpressions']),
- (path_from_root('tools', 'test-js-optimizer-t2c.js'), open(path_from_root('tools', 'test-js-optimizer-t2c-output.js')).read(),
- ['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']),
+ ['hoistMultiples', 'removeAssignsToUndefined', 'simplifyExpressions']),
(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']),
(path_from_root('tools', 'test-js-optimizer-regs.js'), open(path_from_root('tools', 'test-js-optimizer-regs-output.js')).read(),
['registerize']),
(path_from_root('tools', 'eliminator', 'eliminator-test.js'), open(path_from_root('tools', 'eliminator', 'eliminator-test-output.js')).read(),
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js
index a4c05b70..086ed30e 100644
--- a/tools/js-optimizer.js
+++ b/tools/js-optimizer.js
@@ -169,11 +169,11 @@ function astToSrc(ast, minifyWhitespace) {
// Traverses the children of a node. If the traverse function returns an object,
// replaces the child. If it returns true, stop the traversal and return true.
-function traverseChildren(node, traverse, pre, post, stack) {
+function traverseChildren(node, traverse, pre, post) {
for (var i = 0; i < node.length; i++) {
var subnode = node[i];
if (Array.isArray(subnode)) {
- var subresult = traverse(subnode, pre, post, stack);
+ var subresult = traverse(subnode, pre, post);
if (subresult === true) return true;
if (subresult !== null && typeof subresult === 'object') node[i] = subresult;
}
@@ -189,30 +189,24 @@ function traverseChildren(node, traverse, pre, post, stack) {
// it replaces the passed node in the tree. If null is returned, we stop
// traversing the subelements (but continue otherwise).
// @arg post: A callback to call after traversing all children.
-// @arg stack: If true, a stack will be implemented: If pre does not push on
-// the stack, we push a 0. We pop when we leave the node. The
-// stack is passed as a third parameter to the callbacks.
// @returns: If the root node was replaced, the new root node. If the traversal
// was stopped, true. Otherwise undefined.
-function traverse(node, pre, post, stack) {
+function traverse(node, pre, post) {
var type = node[0], result, len;
var relevant = typeof type === 'string';
if (relevant) {
- if (stack) len = stack.length;
- var result = pre(node, type, stack);
+ var result = pre(node, type);
if (result === true) return true;
if (result && result !== null) node = result; // Continue processing on this node
- if (stack && len === stack.length) stack.push(0);
}
if (result !== null) {
- if (traverseChildren(node, traverse, pre, post, stack) === true) return true;
+ if (traverseChildren(node, traverse, pre, post) === true) return true;
}
if (relevant) {
if (post) {
- var postResult = post(node, type, stack);
+ var postResult = post(node, type);
result = result || postResult;
}
- if (stack) stack.pop();
}
return result;
}
@@ -231,38 +225,12 @@ function traverseGeneratedFunctions(ast, callback) {
}
}
-function traverseGenerated(ast, pre, post, stack) {
+function traverseGenerated(ast, pre, post) {
traverseGeneratedFunctions(ast, function(func) {
- traverse(func, pre, post, stack);
+ traverse(func, pre, post);
});
}
-// Walk the ast in a simple way, with an understanding of which JS variables are defined)
-function traverseWithVariables(ast, callback) {
- traverse(ast, function(node, type, stack) {
- if (type in FUNCTION) {
- stack.push({ type: 'function', vars: node[2] });
- } else if (type === 'var') {
- // Find our function, add our vars
- var func = stack[stack.length-1];
- if (func) {
- func.vars = func.vars.concat(node[1].map(function(varItem) { return varItem[0] }));
- }
- }
- }, function(node, type, stack) {
- if (type === 'toplevel' || type in FUNCTION) {
- // We know all of the variables that are seen here, proceed to do relevant replacements
- var allVars = stack.map(function(item) { return item ? item.vars : [] }).reduce(concatenator, []); // FIXME dictionary for speed?
- traverse(node, function(node2, type2, stack2) {
- // Be careful not to look into our inner functions. They have already been processed.
- if (sum(stack2) > 1 || (type === 'toplevel' && sum(stack2) === 1)) return;
- if (type2 in FUNCTION) stack2.push(1);
- return callback(node2, type2, allVars);
- }, null, []);
- }
- }, []);
-}
-
function emptyNode() { // XXX do we need to create new nodes here? can't we reuse?
return ['toplevel', []]
}
@@ -327,58 +295,6 @@ function dumpSrc(ast) {
printErr(astToSrc(ast));
}
-// Undos closure's creation of global variables with values true, false,
-// undefined, null. These cut down on size, but do not affect gzip size
-// and make JS engine's lives slightly harder (?)
-function unGlobalize(ast) {
-
- throw 'this is deprecated!'; // and does not work with parallel compilation
-
- assert(ast[0] === 'toplevel');
- var values = {};
- // Find global renamings of the relevant values
- ast[1].forEach(function(node, i) {
- if (node[0] != 'var') return;
- node[1] = node[1].filter(function(varItem, j) {
- var ident = varItem[0];
- var value = varItem[1];
- if (!value) return true;
- var possible = false;
- if (jsonCompare(value, NULL_NODE) ||
- jsonCompare(value, UNDEFINED_NODE) ||
- jsonCompare(value, TRUE_NODE) ||
- jsonCompare(value, FALSE_NODE)) {
- possible = true;
- }
- if (!possible) return true;
- // Make sure there are no assignments to this variable. (This isn't fast, we traverse many times..)
- ast[1][i][1][j] = emptyNode();
- var assigned = false;
- traverseWithVariables(ast, function(node, type, allVars) {
- if (type === 'assign' && node[2][0] === 'name' && node[2][1] === ident) assigned = true;
- });
- ast[1][i][1][j] = [ident, value];
- if (!assigned) {
- values[ident] = value;
- return false;
- }
- return true;
- });
-
- if (node[1].length === 0) {
- ast[1][i] = emptyNode();
- }
- });
- traverseWithVariables(ast, function(node, type, allVars) {
- if (type === 'name') {
- var ident = node[1];
- if (ident in values && allVars.indexOf(ident) < 0) {
- return copy(values[ident]);
- }
- }
- });
-}
-
// Closure compiler, when inlining, will insert assignments to
// undefined for the shared variables. However, in compiled code
// - and in library/shell code too! - we should never rely on
@@ -505,10 +421,12 @@ function simplifyExpressions(ast) {
var rerun = true;
while (rerun) {
rerun = false;
- traverse(ast, function process(node, type, stack) {
+ var stack = [];
+ traverse(ast, function process(node, type) {
if (type === 'binary' && node[1] === '|') {
if (node[2][0] === 'num' && node[3][0] === 'num') {
node[2][1] |= node[3][1];
+ stack.push(0);
return node[2];
}
var go = false;
@@ -541,7 +459,7 @@ function simplifyExpressions(ast) {
node[j] = result[j];
}
rerun = true;
- return process(result, result[0], stack);
+ return process(result, result[0]);
} else if (stack[i] === -1) {
break; // Too bad, we can't
}
@@ -557,7 +475,9 @@ function simplifyExpressions(ast) {
} else {
stack.push(-1); // This node is dangerous! Give up if you see this before you see '1'
}
- }, null, []);
+ }, function() {
+ stack.pop();
+ });
}
}
@@ -992,340 +912,6 @@ function simplifyIfs(ast) {
});
}
-
-// 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,
-// to greatly reduce the number of shift operations.
-// XXX this optimization is deprecated and currently invalid: does not handle overflows
-// or non-aligned (round numbers, x >> 2 is a multiple of 4). Both are ok to assume
-// for pointers (undefined behavior otherwise), but invalid in general, and we do
-// no sufficiently-well distinguish the cases.
-function optimizeShiftsInternal(ast, conservative) {
- var MAX_SHIFTS = 3;
- traverseGeneratedFunctions(ast, function(fun) {
- var funMore = true;
- var funFinished = {};
- while (funMore) {
- funMore = false;
- // Recognize variables and parameters
- var vars = {};
- function newVar(name, param, addUse) {
- if (!vars[name]) {
- vars[name] = {
- param: param,
- defs: addUse ? 1 : 0,
- uses: 0,
- timesShifted: [0, 0, 0, 0], // zero shifts of size 0, 1, 2, 3
- benefit: 0,
- primaryShift: -1
- };
- }
- }
- // params
- if (fun[2]) {
- fun[2].forEach(function(arg) {
- newVar(arg, true, true);
- });
- }
- // vars
- // XXX if var has >>=, ignore it here? That means a previous pass already optimized it
- var hasSwitch = traverse(fun, function(node, type) {
- if (type === 'var') {
- node[1].forEach(function(arg) {
- newVar(arg[0], false, arg[1]);
- });
- } else if (type === 'switch') {
- // The relooper can't always optimize functions, and we currently don't work with
- // switch statements when optimizing shifts. Bail.
- return true;
- }
- });
- if (hasSwitch) {
- break;
- }
- // uses and defs TODO: weight uses by being inside a loop (powers). without that, we
- // optimize for code size, not speed.
- traverse(fun, function(node, type, stack) {
- stack.push(node);
- if (type === 'name' && vars[node[1]] && stack[stack.length-2][0] != 'assign') {
- vars[node[1]].uses++;
- } else if (type === 'assign' && node[2][0] === 'name' && vars[node[2][1]]) {
- vars[node[2][1]].defs++;
- }
- }, null, []);
- // First, break up elements inside a shift. This lets us see clearly what to do next.
- traverse(fun, function(node, type) {
- if (type === 'binary' && node[1] === '>>' && node[3][0] === 'num') {
- var shifts = node[3][1];
- if (shifts <= MAX_SHIFTS) {
- // Push the >> inside the value elements
- function addShift(subNode) {
- if (subNode[0] === 'binary' && subNode[1] === '+') {
- subNode[2] = addShift(subNode[2]);
- subNode[3] = addShift(subNode[3]);
- return subNode;
- }
- if (subNode[0] === 'name' && !subNode[2]) { // names are returned with a shift, but we also note their being shifted
- var name = subNode[1];
- if (vars[name]) {
- vars[name].timesShifted[shifts]++;
- subNode[2] = true;
- }
- }
- return ['binary', '>>', subNode, ['num', shifts]];
- }
- return addShift(node[2]);
- }
- }
- });
- traverse(fun, function(node, type) {
- if (node[0] === 'name' && node[2]) {
- return node.slice(0, 2); // clean up our notes
- }
- });
- // At this point, shifted expressions are split up, and we know who the vars are and their info, so we can decide
- // TODO: vars that depend on other vars
- for (var name in vars) {
- var data = vars[name];
- var totalTimesShifted = sum(data.timesShifted);
- if (totalTimesShifted === 0) {
- continue;
- }
- if (totalTimesShifted != Math.max.apply(null, data.timesShifted)) {
- // TODO: Handle multiple different shifts
- continue;
- }
- if (funFinished[name]) continue;
- // We have one shift size (and possible unshifted uses). Consider replacing this variable with a shifted clone. If
- // the estimated benefit is >0, we will do it
- if (data.defs === 1) {
- data.benefit = totalTimesShifted - 2*(data.defs + (data.param ? 1 : 0));
- }
- if (conservative) data.benefit = 0;
- if (data.benefit > 0) {
- funMore = true; // We will reprocess this function
- for (var i = 0; i < 4; i++) {
- if (data.timesShifted[i]) {
- data.primaryShift = i;
- }
- }
- }
- }
- //printErr(JSON.stringify(vars));
- function cleanNotes() { // We need to mark 'name' nodes as 'processed' in some passes here; this cleans the notes up
- traverse(fun, function(node, type) {
- if (node[0] === 'name' && node[2]) {
- return node.slice(0, 2);
- }
- });
- }
- cleanNotes();
- // Apply changes
- function needsShift(name) {
- return vars[name] && vars[name].primaryShift >= 0;
- }
- for (var name in vars) { // add shifts for params and var's for all new variables
- var data = vars[name];
- if (needsShift(name)) {
- if (data.param) {
- fun[3].unshift(['var', [[name + '$s' + data.primaryShift, ['binary', '>>', ['name', name], ['num', data.primaryShift]]]]]);
- } else {
- fun[3].unshift(['var', [[name + '$s' + data.primaryShift]]]);
- }
- }
- }
- traverse(fun, function(node, type, stack) { // add shift to assignments
- stack.push(node);
- if (node[0] === 'assign' && node[1] === true && node[2][0] === 'name' && needsShift(node[2][1]) && !node[2][2]) {
- var name = node[2][1];
- var data = vars[name];
- var parent = stack[stack.length-3];
- var statements = getStatements(parent);
- assert(statements, 'Invalid parent for assign-shift: ' + dump(parent));
- var i = statements.indexOf(stack[stack.length-2]);
- statements.splice(i+1, 0, ['stat', ['assign', true, ['name', name + '$s' + data.primaryShift], ['binary', '>>', ['name', name, true], ['num', data.primaryShift]]]]);
- } else if (node[0] === 'var') {
- var args = node[1];
- for (var i = 0; i < args.length; i++) {
- var arg = args[i];
- var name = arg[0];
- var data = vars[name];
- if (arg[1] && needsShift(name)) {
- args.splice(i+1, 0, [name + '$s' + data.primaryShift, ['binary', '>>', ['name', name, true], ['num', data.primaryShift]]]);
- }
- }
- return node;
- }
- }, null, []);
- cleanNotes();
- traverse(fun, function(node, type, stack) { // replace shifted name with new variable
- stack.push(node);
- if (node[0] === 'binary' && node[1] === '>>' && node[2][0] === 'name' && needsShift(node[2][1]) && node[3][0] === 'num') {
- var name = node[2][1];
- var data = vars[name];
- var parent = stack[stack.length-2];
- // Don't modify in |x$sN = x >> 2|, in normal assigns and in var assigns
- if (parent[0] === 'assign' && parent[2][0] === 'name' && parent[2][1] === name + '$s' + data.primaryShift) return;
- if (parent[0] === name + '$s' + data.primaryShift) return;
- if (node[3][1] === data.primaryShift) {
- return ['name', name + '$s' + data.primaryShift];
- }
- }
- }, null, []);
- cleanNotes();
- var SIMPLE_SHIFTS = set('<<', '>>');
- var more = true;
- while (more) { // combine shifts in the same direction as an optimization
- more = false;
- traverse(fun, function(node, type) {
- if (node[0] === 'binary' && node[1] in SIMPLE_SHIFTS && node[2][0] === 'binary' && node[2][1] === node[1] &&
- node[3][0] === 'num' && node[2][3][0] === 'num') { // do not turn a << b << c into a << b + c; while logically identical, it is slower
- more = true;
- return ['binary', node[1], node[2][2], ['num', node[3][1] + node[2][3][1]]];
- }
- });
- }
- // Before recombining, do some additional optimizations
- traverse(fun, function(node, type) {
- // Apply constant shifts onto constants
- if (type === 'binary' && node[1] === '>>' && node[2][0] === 'num' && node[3][0] === 'num' && node[3][1] <= MAX_SHIFTS) {
- var subNode = node[2];
- var shifts = node[3][1];
- var result = subNode[1] / Math.pow(2, shifts);
- if (result % 1 === 0) {
- subNode[1] = result;
- return subNode;
- }
- }
- // Optimize the case of ($a*80)>>2 into ($a*20)|0
- if (type === 'binary' && node[1] in SIMPLE_SHIFTS &&
- node[2][0] === 'binary' && node[2][1] === '*') {
- var mulNode = node[2];
- if (mulNode[2][0] === 'num') {
- var temp = mulNode[2];
- mulNode[2] = mulNode[3];
- mulNode[3] = temp;
- }
- if (mulNode[3][0] === 'num') {
- if (node[1] === '<<') {
- mulNode[3][1] *= Math.pow(2, node[3][1]);
- node[1] = '|';
- node[3][1] = 0;
- return node;
- } else {
- if (mulNode[3][1] % Math.pow(2, node[3][1]) === 0) {
- mulNode[3][1] /= Math.pow(2, node[3][1]);
- node[1] = '|';
- node[3][1] = 0;
- return node;
- }
- }
- }
- }
- /* XXX - theoretically useful optimization(s), but commented out as not helpful in practice
- // Transform (x << 2) >> 2 into x & mask or something even simpler
- if (type === 'binary' && node[1] === '>>' && node[3][0] === 'num' &&
- node[2][0] === 'binary' && node[2][1] === '<<' && node[2][3][0] === 'num' && node[3][1] === node[2][3][1]) {
- var subNode = node[2];
- var shifts = node[3][1];
- var mask = ((0xffffffff << shifts) >>> shifts) | 0;
- return ['binary', '&', subNode[2], ['num', mask]];
- //return ['binary', '|', subNode[2], ['num', 0]];
- //return subNode[2];
- }
- */
- });
- // Re-combine remaining shifts, to undo the breaking up we did before. may require reordering inside +'s
- traverse(fun, function(node, type, stack) {
- stack.push(node);
- if (type === 'binary' && node[1] === '+' && (stack[stack.length-2][0] != 'binary' || stack[stack.length-2][1] !== '+')) {
- // 'Flatten' added items
- var addedItems = [];
- function flatten(node) {
- if (node[0] === 'binary' && node[1] === '+') {
- flatten(node[2]);
- flatten(node[3]);
- } else {
- addedItems.push(node);
- }
- }
- flatten(node);
- var originalOrder = addedItems.slice();
- function key(node) { // a unique value for all relevant shifts for recombining, non-unique for stuff we don't need to bother with
- function originalOrderKey(item) {
- return -originalOrder.indexOf(item);
- }
- if (node[0] === 'binary' && node[1] in SIMPLE_SHIFTS) {
- if (node[3][0] === 'num' && node[3][1] <= MAX_SHIFTS) return 2*node[3][1] + (node[1] === '>>' ? 100 : 0); // 0-106
- return (node[1] === '>>' ? 20000 : 10000) + originalOrderKey(node);
- }
- if (node[0] === 'num') return -20000 + node[1];
- return -10000 + originalOrderKey(node); // Don't modify the original order if we don't modify anything
- }
- for (var i = 0; i < addedItems.length; i++) {
- if (addedItems[i][0] === 'string') return; // this node is not relevant for us
- }
- addedItems.sort(function(node1, node2) {
- return key(node1) - key(node2);
- });
- // Regenerate items, now sorted
- var i = 0;
- while (i < addedItems.length-1) { // re-combine inside addedItems
- var k = key(addedItems[i]), k1 = key(addedItems[i+1]);
- if (k === k1 && k >= 0 && k1 <= 106) {
- addedItems[i] = ['binary', addedItems[i][1], ['binary', '+', addedItems[i][2], addedItems[i+1][2]], addedItems[i][3]];
- addedItems.splice(i+1, 1);
- } else {
- i++;
- }
- }
- var num = 0;
- for (i = 0; i < addedItems.length; i++) { // combine all numbers into one
- if (addedItems[i][0] === 'num') {
- num += addedItems[i][1];
- addedItems.splice(i, 1);
- i--;
- }
- }
- if (num != 0) { // add the numbers into an existing shift, we
- // prefer (x+5)>>7 over (x>>7)+5 , since >>'s result is known to be 32-bit and is more easily optimized.
- // Also, in the former we can avoid the parentheses, which saves a little space (the number will be bigger,
- // so it might take more space, but normally at most one more digit).
- var added = false;
- for (i = 0; i < addedItems.length; i++) {
- if (addedItems[i][0] === 'binary' && addedItems[i][1] === '>>' && addedItems[i][3][0] === 'num' && addedItems[i][3][1] <= MAX_SHIFTS) {
- addedItems[i] = ['binary', '>>', ['binary', '+', addedItems[i][2], ['num', num << addedItems[i][3][1]]], addedItems[i][3]];
- added = true;
- }
- }
- if (!added) {
- addedItems.unshift(['num', num]);
- }
- }
- var ret = addedItems.pop();
- while (addedItems.length > 0) { // re-create AST from addedItems
- ret = ['binary', '+', ret, addedItems.pop()];
- }
- return ret;
- }
- }, null, []);
- // Note finished variables
- for (var name in vars) {
- funFinished[name] = true;
- }
- }
- });
-}
-
-function optimizeShiftsConservative(ast) {
- optimizeShiftsInternal(ast, true);
-}
-
-function optimizeShiftsAggressive(ast) {
- optimizeShiftsInternal(ast, false);
-}
-
// We often have branchings that are simplified so one end vanishes, and
// we then get
// if (!(x < 5))
@@ -5449,13 +5035,10 @@ var passes = {
// passes
dumpAst: dumpAst,
dumpSrc: dumpSrc,
- unGlobalize: unGlobalize,
removeAssignsToUndefined: removeAssignsToUndefined,
//removeUnneededLabelSettings: removeUnneededLabelSettings,
simplifyExpressions: simplifyExpressions,
simplifyIfs: simplifyIfs,
- optimizeShiftsConservative: optimizeShiftsConservative,
- optimizeShiftsAggressive: optimizeShiftsAggressive,
hoistMultiples: hoistMultiples,
loopOptimizer: loopOptimizer,
registerize: registerize,
diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js
index 5e5ff29a..41f79f76 100644
--- a/tools/test-js-optimizer-output.js
+++ b/tools/test-js-optimizer-output.js
@@ -4,25 +4,25 @@ function expr() {
function loopy() {
$while_body$2 : while (1) {
$ok = 1;
- while (1) {
- if ($ok) break;
+ $for_cond$4 : while (1) {
+ if ($ok) break $for_cond$4;
var $inc = $ok + 1;
if ($inc == 9999) break $while_body$2;
}
- continue;
+ continue $while_body$2;
}
next();
- while (1) {
+ b$while_body$2 : while (1) {
$ok = 1;
- while (1) {
- if ($ok) break;
+ b$for_cond$4 : while (1) {
+ if ($ok) break b$for_cond$4;
var $inc = $ok + 1;
}
- continue;
+ continue b$while_body$2;
}
next();
- do {
- if (!$ok) break;
+ $once : do {
+ if (!$ok) break $once;
something();
} while (0);
next();
@@ -33,7 +33,9 @@ function loopy() {
something();
} while (0);
next();
- something();
+ c$once : do {
+ something();
+ } while (0);
}
function bits() {
print(($s & 65535) + ((($f & 65535) << 16 >> 16) * (($f & 65535) << 16 >> 16) | 0) % 256 & 65535);
@@ -68,9 +70,9 @@ function hoisting() {
}
} while (0);
pause(2);
- do {
+ cheez : do {
if ($i < $N) {
- if (callOther()) break;
+ if (callOther()) break cheez;
}
} while (0);
pause(3);
@@ -97,7 +99,7 @@ function hoisting() {
somethingElse();
}
pause(7);
- while (1) {
+ free : while (1) {
if ($i >= $N) {
label = 3;
break;
@@ -110,24 +112,26 @@ function hoisting() {
}
pause(8);
var $cmp95 = $69 == -1;
- do {
+ $if_then96$$if_end110thread_pre_split$48 : do {
if ($cmp95) {
if (!$cmp103) {
label = 38;
- break;
+ break $if_then96$$if_end110thread_pre_split$48;
}
if (!$cmp106) {
label = 38;
- break;
+ break $if_then96$$if_end110thread_pre_split$48;
}
label = 39;
- break;
+ break $if_then96$$if_end110thread_pre_split$48;
}
label = 38;
} while (0);
- if (label == 38) {
- var $79 = $_pr6;
- }
+ $if_end110$$if_end110thread_pre_split$52 : do {
+ if (label == 38) {
+ var $79 = $_pr6;
+ }
+ } while (0);
pause(9);
var $cmp70 = ($call69 | 0) != 0;
pause(10);
@@ -191,24 +195,26 @@ function sleep() {
return 0;
}
function demangle($cmp) {
- do {
+ $if_then$$lor_lhs_false$2 : do {
if (!$cmp) {
if (something()) {
label = 3;
- break;
+ break $if_then$$lor_lhs_false$2;
}
more();
- break;
+ break $if_then$$lor_lhs_false$2;
}
label = 3;
} while (0);
- if (label == 3) {
- final();
- }
+ $if_then$$return$6 : do {
+ if (label == 3) {
+ final();
+ }
+ } while (0);
}
function lua() {
- while (1) {
- do {
+ $5$98 : while (1) {
+ $15$$16$101 : do {
if (!$14) {
var $17 = $i;
var $18 = $3;
@@ -217,7 +223,7 @@ function lua() {
var $21 = $20 + 1 | 0;
var $22 = HEAP8[$21];
var $23 = $22 << 24 >> 24;
- break;
+ break $15$$16$101;
}
} while (0);
}
@@ -236,14 +242,16 @@ function lua() {
}
}
function moreLabels() {
- while (1) {
+ $for_cond$2 : while (1) {
if (!$cmp) {
- break;
+ break $for_cond$2;
}
- if ($cmp1) {
- break;
- }
- inc();
+ $if_then$$for_inc$5 : do {
+ if ($cmp1) {
+ break $for_cond$2;
+ }
+ inc();
+ } while (0);
}
pause(999);
$while_body$$while_end$31 : do {
diff --git a/tools/test-js-optimizer-t2-output.js b/tools/test-js-optimizer-t2-output.js
deleted file mode 100644
index 334d7999..00000000
--- a/tools/test-js-optimizer-t2-output.js
+++ /dev/null
@@ -1,91 +0,0 @@
-function shifty($id2) {
- var $tp$s2;
- var $parameters_addr$s2;
- var $wavelet38$s2;
- var _dwt_norms_real$s2;
- var $a_addr$s2;
- var _idents$s2;
- var $id3$s3;
- var $id2$s1 = $id2 >> 1;
- q(HEAP32[$id >> 2]);
- q(HEAP32[$id + 40 >> 2]);
- q(HEAP32[$id + 80 >> 2]);
- q(HEAP32[unknown1 + unknown2 + $id >> 2]);
- q(HEAP32[unknown1 + $id + unknown2 >> 2]);
- var localUnchanged1 = get(1), localUnchanged2 = get(1);
- q(HEAP32[localUnchanged1 + $id + localUnchanged2 >> 2]);
- q($id >> _something_);
- $id = q("..");
- q($id << _somethingElse_);
- pause(-1);
- q(HEAP32[$id2$s1]);
- q(HEAP32[$id2$s1]);
- q(HEAP32[$id2$s1]);
- q(HEAP32[$id2$s1]);
- q(HEAP32[$id2$s1 + 20]);
- q(HEAP32[$id2$s1 + 40]);
- var $id3 = get(74), $id3$s3 = $id3 >> 3;
- q(HEAP32[$id3$s3]);
- q(HEAP32[$id3$s3 + 5]);
- q(HEAP32[$id3$s3 + 10]);
- q($id3);
- pause(0);
- var _idents = get("abc"), _idents$s2 = _idents >> 2;
- q(HEAP32[HEAP32[_idents$s2] + 8 >> 2]);
- q(HEAP32[HEAP32[_idents$s2] + 8 >> 2]);
- q(HEAP32[HEAP32[_idents$s2] + 8 >> 2]);
- pause(1);
- var $sn_addr = get(12), $a_addr = get(999), $a_addr$s2 = $a_addr >> 2;
- var $i = get(112233);
- q(HEAP32[(($sn_addr - 1 << 1) + 1 << 2 >> 2) + $a_addr$s2]);
- q(HEAP32[(($i - 1 << 1) + 1 << 2 >> 2) + $a_addr$s2]);
- q(HEAP32[($i << 3 >> 2) + $a_addr$s2]);
- q(HEAP32[($i << 2 >> 2) + $a_addr$s2]);
- q($a_addr$s2, z($a_addr$s2));
- pause(2);
- var $level = HEAP[get(322) >> 2];
- var _dwt_norms_real = get("a"), _dwt_norms_real$s2 = _dwt_norms_real >> 2, $orient = get("cheez");
- q(HEAP32[($level << 3 >> 2) + _dwt_norms_real$s2 + ($orient * 20 | 0)]);
- q(HEAP32[(($level << 3) + 4 >> 2) + _dwt_norms_real$s2 + ($orient * 20 | 0)]);
- q(HEAP32[(($level << 3) + 8 >> 2) + _dwt_norms_real$s2 + ($orient * 20 | 0)]);
- pause(3);
- var $wavelet38 = get(38), $wavelet38$s2 = $wavelet38 >> 2;
- $k = $a_addr;
- q(HEAPF32[HEAP32[$wavelet38$s2] + ($k << 4) + 8 >> 2]);
- q(HEAPF32[HEAP32[$wavelet38$s2] + ($k << 4) + 12 >> 2]);
- q(HEAPF32[HEAP32[$wavelet38$s2] + ($k << 4) + 400 >> 2]);
- pause(4);
- var $p = $k, $parameters_addr = get("burger"), $parameters_addr$s2 = $parameters_addr >> 2;
- q(HEAP32[(($p << 2) + 5624 >> 2) + $parameters_addr$s2]);
- q(HEAP32[(($p << 2) + 5644 >> 2) + $parameters_addr$s2]);
- q(HEAP32[(($p << 2) + 5664 >> 2) + $parameters_addr$s2]);
- pause(5);
- var $res_spec242 = get($real), $cp = get("b"), $tileno = arguments[2];
- q(HEAP32[(($res_spec242 - 1 << 2) + 5624 >> 2) + $parameters_addr$s2]);
- q(HEAP32[(HEAP32[$cp + 108 >> 2] + 420 >> 2) + ($tileno * 1397 | 0)]);
- pause(6);
- q($idx << 3);
- q(1 << $idx << 1);
- print(INDENT + "Entering: _main" + "hi");
- pause(7);
- var $tp = get("tp"), $tp$s2 = $tp >> 2;
- q($tp$s2);
- q($tp$s2);
- q($tp$s2);
- HEAP32[$H400] = $tp;
- HEAP32[$tp] = 5;
- HEAP32[$tp$s2] = 5;
- HEAP32[HEAP[$tp$s2]] = 5;
- HEAP32[HEAP[$tp$s2] >> 2] = 5;
- pause(7);
- q(go() >> 1 << 1);
- q(go() << 1 >> 1);
- q(go() >> 2);
- q(go() << 2);
- q(go() >> 8 << 8);
- q(go() << 8 >> 8);
- q(go() >> 16);
- q(go() << 16);
- q(go() + 2 >> 2);
-}
-
diff --git a/tools/test-js-optimizer-t2.js b/tools/test-js-optimizer-t2.js
deleted file mode 100644
index 8dd82485..00000000
--- a/tools/test-js-optimizer-t2.js
+++ /dev/null
@@ -1,92 +0,0 @@
-// TODO also with >> 1 and >> 3
-// also HEAP*U*, and HEAP8, 16
-function shifty($id2) {
- // $id is a non-ssa, $id2 is a param. both should be replaced with a shifted version
- q(HEAP32[$id >> 2]);
- q(HEAP32[($id + 40) >> 2]);
- q(HEAP32[($id + 80 | 0) >> 2]);
- q(HEAP32[(unknown1 + unknown2 + $id) >> 2]);
- q(HEAP32[(unknown1 + $id + unknown2) >> 2]); // unknowns should be shifted together
- var localUnchanged1 = get(1), localUnchanged2 = get(1);
- q(HEAP32[(localUnchanged1 + $id + localUnchanged2) >> 2]); // unknowns should be shifted together
- q($id >> _something_); // non-fixed shift
- $id = q('..');
- q($id << _somethingElse_); // non-fixed shift
- pause(-1);
- q(HEAP32[$id2 >> 1]);
- q(HEAP32[$id2 >> 1]);
- q(HEAP32[$id2 >> 1]);
- q(HEAP32[$id2 >> 1]);
- q(HEAP32[($id2 + 40) >> 1]);
- q(HEAP32[($id2 + 80 | 0) >> 1]);
- var $id3 = get(74);
- q(HEAP32[$id3 >> 3]);
- q(HEAP32[($id3 + 40) >> 3]);
- q(HEAP32[($id3 + 80 | 0) >> 3]);
- q($id3);
- pause(0);
- // similar, but inside another HEAP
- var _idents = get('abc');
- q(HEAP32[(HEAP32[_idents >> 2] + 8 | 0) >> 2]);
- q(HEAP32[(HEAP32[_idents >> 2] + 8 | 0) >> 2]);
- q(HEAP32[(HEAP32[_idents >> 2] + 8 | 0) >> 2]);
- pause(1);
- // $i's shifts should consolidate (the last should be 0..?
- // since we may have had |0 in the middle!)
- var $sn_addr = get(12), $a_addr = get(999);
- var $i = get(112233);
- q(HEAP32[($a_addr + ((($sn_addr - 1 << 1) + 1 | 0) << 2) | 0) >> 2]);
- q(HEAP32[($a_addr + ((($i - 1 << 1) + 1 | 0) << 2) | 0) >> 2]);
- q(HEAP32[($a_addr + (($i << 1 | 0) << 2) | 0) >> 2]);
- q(HEAP32[($a_addr + ($i << 2)) >> 2]);
- q($a_addr >> 2, z($a_addr >> 2));
- pause(2);
- var $level = HEAP[get(322) >> 2]; // ignore this
- var _dwt_norms_real = get('a'), $orient = get('cheez');
- q(HEAP32[(_dwt_norms_real + $orient * 80 + ($level << 3) | 0) >> 2]);
- q(HEAP32[(_dwt_norms_real + $orient * 80 + ($level << 3) + 4 | 0) >> 2]);
- q(HEAP32[(_dwt_norms_real + $orient * 80 + ($level << 3) + 8 | 0) >> 2]);
- pause(3);
- // reuse $a_addr here
- var $wavelet38 = get(38);
- $k = $a_addr;
- q(HEAPF32[(HEAP32[$wavelet38 >> 2] + ($k << 4) + 8 | 0) >> 2]);
- q(HEAPF32[(HEAP32[$wavelet38 >> 2] + ($k << 4) + 12 | 0) >> 2]);
- q(HEAPF32[(HEAP32[$wavelet38 >> 2] + ($k << 4) + 400 | 0) >> 2]);
- pause(4);
- // reuse $k, which already reuses $a_addr
- var $p = $k, $parameters_addr = get('burger')
- q(HEAP32[($parameters_addr + 5624 + ($p << 2) | 0) >> 2]);
- q(HEAP32[($parameters_addr + 5644 + ($p << 2) | 0) >> 2]);
- q(HEAP32[($parameters_addr + 5664 + ($p << 2) | 0) >> 2]);
- pause(5);
- // loops count as more uses!
- var $res_spec242 = get($real), $cp = get('b'), $tileno = arguments[2];
- q(HEAP32[($parameters_addr + 5624 + (($res_spec242 - 1 | 0) << 2) | 0) >> 2]);
- q(HEAP32[(HEAP32[($cp + 108 | 0) >> 2] + $tileno * 5588 + 420 | 0) >> 2]);
- pause(6);
- q($idx << 1 << 2);
- q(1 << $idx << 1); // Do not turn this into the slower 1 << $idx + 1 (which is identical though)
- print(INDENT + "Entering: _main" + "hi"); // this order should not be modified
- pause(7);
- var $tp = get('tp');
- q($tp >> 2);
- q($tp >> 2);
- q($tp >> 2);
- HEAP32[$H400]