aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2013-04-20 16:02:42 -0700
committerAlon Zakai <alonzakai@gmail.com>2013-04-20 16:02:42 -0700
commit6f8af49c568abfb3b4203f1d3dc95e12fe573986 (patch)
tree5694a8ac1f6ab81aa0304e4701a4d5cdd2e3bffe
parent31872fbd01ca23962d954ca40232c7b8bfde58fe (diff)
optimize HEAPU?8[..] << 24 >> 24 and similar
-rw-r--r--tools/js-optimizer.js36
-rw-r--r--tools/test-js-optimizer-asm-pre-output.js20
-rw-r--r--tools/test-js-optimizer-asm-pre.js23
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"]