diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-04-20 16:02:42 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-04-20 16:02:42 -0700 |
commit | 6f8af49c568abfb3b4203f1d3dc95e12fe573986 (patch) | |
tree | 5694a8ac1f6ab81aa0304e4701a4d5cdd2e3bffe | |
parent | 31872fbd01ca23962d954ca40232c7b8bfde58fe (diff) |
optimize HEAPU?8[..] << 24 >> 24 and similar
-rw-r--r-- | tools/js-optimizer.js | 36 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 20 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 23 |
3 files changed, 71 insertions, 8 deletions
diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 598287db..5601f65c 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -452,7 +452,16 @@ function simplifyExpressionsPre(ast) { }, null, []); } - // &-related optimizations + // & and heap-related optimizations + + var heapBits, heapUnsigned; + function parseHeap(name) { + if (name.substr(0, 4) != 'HEAP') return false; + heapUnsigned = name[4] == 'U'; + heapBits = parseInt(name.substr(heapUnsigned ? 5 : 4)); + return true; + } + traverseGenerated(ast, function(node, type) { if (type == 'binary' && node[1] == '&' && node[3][0] == 'num') { if (node[2][0] == 'num') return ['num', node[2][1] & node[3][1]]; @@ -465,12 +474,10 @@ function simplifyExpressionsPre(ast) { } else if (input[0] == 'sub' && input[1][0] == 'name') { // HEAP8[..] & 255 => HEAPU8[..] var name = input[1][1]; - if (name.substr(0, 4) == 'HEAP') { - var unsigned = name[4] == 'U'; - var bits = parseInt(name.substr(unsigned ? 5 : 4)); - if (amount == Math.pow(2, bits)-1) { - if (!unsigned) { - input[1][1] = 'HEAPU' + bits; // make unsigned + if (parseHeap(name)) { + if (amount == Math.pow(2, heapBits)-1) { + if (!heapUnsigned) { + input[1][1] = 'HEAPU' + heapBits; // make unsigned } if (asm) { // we cannot return HEAPU8 without a coercion, but at least we do HEAP8 & 255 => HEAPU8 | 0 @@ -482,6 +489,21 @@ function simplifyExpressionsPre(ast) { } } } + } else if (type == 'binary' && node[1] == '>>' && node[3][0] == 'num' && + node[2][0] == 'binary' && node[2][1] == '<<' && node[2][3][0] == 'num' && + node[2][2][0] == 'sub' && node[2][2][1][0] == 'name') { + // collapse HEAPU?8[..] << 24 >> 24 etc. into HEAP8[..] | 0 + var amount = node[3][1]; + var name = node[2][2][1][1]; + if (amount == node[2][3][1] && parseHeap(name)) { + if (heapBits == 32 - amount) { + node[2][2][1][1] = 'HEAP' + heapBits; + node[1] = '|'; + node[2] = node[2][2]; + node[3][1] = 0; + return node; + } + } } }); diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 53619c84..72608aa8 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -73,4 +73,24 @@ function retf() { } return +0; } +function i32_8() { + if ((HEAP8[$4 & 16777215] | 0) == 0) { + print(5); + } + if ((HEAP8[$5 & 16777215] | 0) == 0) { + print(5); + } + if ((HEAP8[$6 & 16777215] | 0) == 0) { + print(5); + } + if ((HEAP8[$7 & 16777215] | 0) == 0) { + print(5); + } + if (HEAPU8[$8 & 16777215] << 24 >> 16 == 0) { + print(5); + } + if (HEAPU8[$9 & 16777215] << 16 >> 16 == 0) { + print(5); + } +} diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index 0fb7050f..f2ffaef4 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -74,4 +74,25 @@ function retf() { } // missing final return, need it as a float } -// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf"] +function i32_8() { + if (((HEAP8[$4 & 16777215] | 0) << 24 >> 24) == 0) { + print(5); + } + if ((HEAP8[$5 & 16777215] << 24 >> 24) == 0) { + print(5); + } + if (((HEAPU8[$6 & 16777215] | 0) << 24 >> 24) == 0) { + print(5); + } + if ((HEAPU8[$7 & 16777215] << 24 >> 24) == 0) { + print(5); + } + // non-valid + if ((HEAPU8[$8 & 16777215] << 24 >> 16) == 0) { + print(5); + } + if ((HEAPU8[$9 & 16777215] << 16 >> 16) == 0) { + print(5); + } +} +// EMSCRIPTEN_GENERATED_FUNCTIONS: ["a", "b", "rett", "ret2t", "retf", "i32_8"] |