diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index a52ad6b71..9e0307dab 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -1596,7 +1596,15 @@ function registerize(ast) { var varLevels = {}; var possibles = {}; var unoptimizables = {}; - traverse(fun, function(node, type) { + function purgeLevel() { + // Invalidate all dominating on this level, further users make it unoptimizable + for (var name in levelDominations[level]) { + varLevels[name] = 0; + } + levelDominations[level] = null; + level--; + } + traverse(fun, function possibilifier(node, type) { if (type == 'name') { var name = node[1]; if (localVars[name]) { @@ -1617,16 +1625,49 @@ function registerize(ast) { } } } else if (type in CONTROL_FLOW) { - level++; - } - }, function(node, type) { - if (type in CONTROL_FLOW) { - // Invalidate all dominating on this level, further users make it unoptimizable - for (var name in levelDominations[level]) { - varLevels[name] = 0; + // recurse children, in the context of a loop + switch(type) { + case 'while': case 'do': { + traverse(node[1], possibilifier); + level++; + traverse(node[2], possibilifier); + purgeLevel(); + break; + } + case 'for': { + traverse(node[1], possibilifier); + for (var i = 2; i <= 4; i++) { + level++; + traverse(node[i], possibilifier); + purgeLevel(); + } + break; + } + case 'if': { + traverse(node[1], possibilifier); + level++; + traverse(node[2], possibilifier); + purgeLevel(); + if (node[3]) { + level++; + traverse(node[3], possibilifier); + purgeLevel(); + } + break; + } + case 'switch': { + traverse(node[1], possibilifier); + var cases = node[2]; + for (var i = 0; i < cases.length; i++) { + level++; + traverse(cases[i][1], possibilifier); + purgeLevel(); + } + break; + } + default: throw dumpAst(node); } - levelDominations[level] = null; - level--; + return null; // prevent recursion into children, which we already did } }); var optimizables = {}; @@ -1635,6 +1676,10 @@ function registerize(ast) { if (!unoptimizables[possible]) optimizables[possible] = 1; } } + + //printErr('optimizables: ' + JSON.stringify(optimizables)); + //printErr('unoptimizables: ' + JSON.stringify(unoptimizables)); + // Go through the function's code, assigning 'registers'. // The only tricky bit is to keep variables locked on a register through loops, // since they can potentially be returned to. Optimizable variables lock onto diff --git a/tools/test-js-optimizer-asm-regs-output.js b/tools/test-js-optimizer-asm-regs-output.js index ba2316ea1..c2efa506d 100644 --- a/tools/test-js-optimizer-asm-regs-output.js +++ b/tools/test-js-optimizer-asm-regs-output.js @@ -38,4 +38,69 @@ function switchey(d1, i2) { return 20; } } +function switchey2() { + var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, d6 = +0, d7 = +0, i8 = 0, i9 = 0; + i1 = STACKTOP; + STACKTOP = STACKTOP + 8 | 0; + i2 = 1; + while (1) switch (i2 | 0) { + case 1: + i3 = i1 | 0; + __ZN6RandomC1Ev(i3); + i4 = 0; + i5 = 0; + i2 = 2; + break; + case 2: + d6 = +__ZN6Random3getEf(8, +1); + d7 = +__ZN6Random3getEf(i3, +1); + _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d6, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d7, tempInt) | 0); + i8 = (d6 != d7 & 1) + i5 | 0; + i9 = i4 + 1 | 0; + if ((i9 | 0) < 100) { + i4 = i9; + i5 = i8; + i2 = 2; + break; + } else { + i2 = 3; + break; + } + case 3: + _printf(16, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[CHECK_ALIGN_4(tempInt | 0) >> 2] = i8, tempInt) | 0); + STACKTOP = i1; + return 0; + } + return 0; +} +function iffey() { + var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, d6 = +0, d7 = +0, i8 = 0, i9 = 0; + i1 = STACKTOP; + STACKTOP = STACKTOP + 8 | 0; + i2 = 1; + while (1) { + if (i2 | 0) { + i3 = i1 | 0; + __ZN6RandomC1Ev(i3); + i4 = 0; + i5 = 0; + i2 = 2; + } else { + d6 = +__ZN6Random3getEf(8, +1); + d7 = +__ZN6Random3getEf(i3, +1); + _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d6, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d7, tempInt) | 0); + i8 = (d6 != d7 & 1) + i5 | 0; + i9 = i4 + 1 | 0; + if ((i9 | 0) < 100) { + i4 = i9; + i5 = i8; + i2 = 2; + } else { + i2 = 3; + return 10; + } + } + } + return 0; +} diff --git a/tools/test-js-optimizer-asm-regs.js b/tools/test-js-optimizer-asm-regs.js index 64797e387..8c3a1c988 100644 --- a/tools/test-js-optimizer-asm-regs.js +++ b/tools/test-js-optimizer-asm-regs.js @@ -41,5 +41,70 @@ function switchey(x, y) { return 20; } } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "stackRestore", "switchey"] +function switchey2() { + var $rng2 = 0, $count_06 = 0, $i_05 = 0, $2 = +0, $3 = +0, $count_1 = 0, $9 = 0, label = 0, __stackBase__ = 0; + __stackBase__ = STACKTOP; + STACKTOP = STACKTOP + 8 | 0; + label = 1; + while (1) switch (label | 0) { + case 1: + $rng2 = __stackBase__ | 0; + __ZN6RandomC1Ev($rng2); + $i_05 = 0; + $count_06 = 0; + label = 2; + break; + case 2: + $2 = +__ZN6Random3getEf(8, +1); + $3 = +__ZN6Random3getEf($rng2, +1); + _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = $2, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = $3, tempInt) | 0); + $count_1 = ($2 != $3 & 1) + $count_06 | 0; + $9 = $i_05 + 1 | 0; + if (($9 | 0) < 100) { + $i_05 = $9; + $count_06 = $count_1; + label = 2; + break; + } else { + label = 3; + break; + } + case 3: + _printf(16, (tempInt = STACKTOP, STACKTOP = STACKTOP + 8 | 0, HEAP32[CHECK_ALIGN_4(tempInt | 0) >> 2] = $count_1, tempInt) | 0); + STACKTOP = __stackBase__; + return 0; + } + return 0; +} +function iffey() { + var $rng2 = 0, $count_06 = 0, $i_05 = 0, $2 = +0, $3 = +0, $count_1 = 0, $9 = 0, label = 0, __stackBase__ = 0; + __stackBase__ = STACKTOP; + STACKTOP = STACKTOP + 8 | 0; + label = 1; + while (1) { + if (label | 0) { + $rng2 = __stackBase__ | 0; + __ZN6RandomC1Ev($rng2); + $i_05 = 0; + $count_06 = 0; + label = 2; + } else { + $2 = +__ZN6Random3getEf(8, +1); + $3 = +__ZN6Random3getEf($rng2, +1); + _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = $2, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = $3, tempInt) | 0); + $count_1 = ($2 != $3 & 1) + $count_06 | 0; + $9 = $i_05 + 1 | 0; + if (($9 | 0) < 100) { + $i_05 = $9; + $count_06 = $count_1; + label = 2; + } else { + label = 3; + return 10; + } + } + } + return 0; +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["asm", "_doit", "stackRestore", "switchey", "switchey2", "iffey"]