diff options
-rw-r--r-- | tools/js-optimizer.js | 41 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-regs-harder-output.js | 28 |
2 files changed, 26 insertions, 43 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 78676681..abb854c6 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -2460,55 +2460,40 @@ function registerizeHarder(ast) { buildFlowGraph(node[2]); break; case 'switch': - // This is horrific. It need to capture the default flow-through - // logic of sequential case bodies, as well as the theoretical - // sequential evaluation of each case clause. - // TODO: simplify based on asmjs switch-statement restrictions. + // Emscripten generates switch statements of a very limited + // form: all case clauses are numeric literals, and all + // case bodies end with a break. So it's basically equivalent + // to a multi-way 'if' statement. isInExpr++; buildFlowGraph(node[1]); isInExpr--; var jCheckExit = markJunction(); var jExit = addJunction(); pushActiveLabels(null, jExit); - // Process all cases as a sequential chain of checks. - // Process all case bodies as one big flow-through statement. - // They might break themselves out of it but this implements the - // default fall-through case logic. var hasDefault = false; - var jPrevCaseExit = jCheckExit; - var jPrevBodyExit = jCheckExit; for (var i=0; i<node[2].length; i++) { - // In the general case we'll need a basic block for the case clause. - // Try to avoid it for common, simple, non-var-using cases. + setJunction(jCheckExit); if (!node[2][i][0]) { hasDefault = true; } else { if (node[2][i][0][0] !== 'num') { - setJunction(jPrevCaseExit); - isInExpr++; - buildFlowGraph(node[2][i][0]); - isInExpr--; - jPrevCaseExit = markJunction(); + if (node[2][i][0][0] !== 'unary-prefix' || node[2][i][0][2][0] !== 'num') { + assert(false, 'non-numeric switch case clause'); + } } - } - // The next case body flows from the exit of the prev one, - // or may be entered directly from the case statement exit. - setJunction(jPrevCaseExit); - if (jPrevBodyExit !== jCheckExit) { - joinJunction(jPrevBodyExit); + addPreCondTrue(['binary', '==', node[1], node[2][i][0]]); } for (var j = 0; j < node[2][i][1].length; j++) { buildFlowGraph(node[2][i][1][j]); } - jPrevBodyExit = markJunction(); + if (currEntryJunction !== null, 'switch case body did not break'); } - markJunction(jExit); // If there was no default case, we also need an empty block - // linking straight from entry to exit. - if (!hasDefault && jCheckExit !== jPrevBodyExit) { + // linking straight from the test evaluation to the exit. + if (!hasDefault) { setJunction(jCheckExit); - joinJunction(jExit); } + markJunction(jExit); popActiveLabels() break; case 'return': diff --git a/tools/test-js-optimizer-asm-regs-harder-output.js b/tools/test-js-optimizer-asm-regs-harder-output.js index 710018bb..448fb67a 100644 --- a/tools/test-js-optimizer-asm-regs-harder-output.js +++ b/tools/test-js-optimizer-asm-regs-harder-output.js @@ -37,31 +37,29 @@ function switchey(d1, i2) { } } function switchey2() { - var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, i6 = 0, d7 = +0, d8 = +0; + var i1 = 0, i2 = 0, i3 = 0, i4 = 0, i5 = 0, d6 = +0, d7 = +0; i2 = STACKTOP; STACKTOP = STACKTOP + 8 | 0; - i6 = 1; - while (1) switch (i6 | 0) { + i3 = 1; + while (1) switch (i3 | 0) { case 1: i1 = i2 | 0; __ZN6RandomC1Ev(i1); i4 = 0; - i3 = 0; - i6 = 2; + i5 = 0; + i3 = 2; break; case 2: - d8 = +__ZN6Random3getEf(8, +1); - d7 = +__ZN6Random3getEf(i1, +1); - _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d8, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d7, tempInt) | 0); - i5 = (d8 != d7 & 1) + i3 | 0; - i6 = i4 + 1 | 0; - if ((i6 | 0) < 100) { - i4 = i6; - i3 = i5; - i6 = 2; + d7 = +__ZN6Random3getEf(8, +1); + d6 = +__ZN6Random3getEf(i1, +1); + _printf(24, (tempInt = STACKTOP, STACKTOP = STACKTOP + 16 | 0, HEAPF64[CHECK_ALIGN_8(tempInt | 0) >> 3] = d7, HEAPF64[CHECK_ALIGN_8(tempInt + 8 | 0) >> 3] = d6, tempInt) | 0); + i5 = (d7 != d6 & 1) + i5 | 0; + i4 = i4 + 1 | 0; + if ((i4 | 0) < 100) { + i3 = 2; break; } else { - i6 = 3; + i3 = 3; break; } case 3: |