summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-05-15 17:50:49 -0700
committerGitHub <noreply@github.com>2019-05-15 17:50:49 -0700
commitf86375ac2121db5fec236f4e35f73adde9318a8c (patch)
tree5f6cf343615df7e97c988c719ad5a3d214e13f9d /src
parentcff4b756e61dad01aa1965ceb4d76a24de7413c5 (diff)
downloadbinaryen-f86375ac2121db5fec236f4e35f73adde9318a8c.tar.gz
binaryen-f86375ac2121db5fec236f4e35f73adde9318a8c.tar.bz2
binaryen-f86375ac2121db5fec236f4e35f73adde9318a8c.zip
wasm2js: more coercion optimization (#2109)
Diffstat (limited to 'src')
-rw-r--r--src/tools/wasm2js.cpp57
1 files changed, 39 insertions, 18 deletions
diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp
index b3f8068e2..731efbee0 100644
--- a/src/tools/wasm2js.cpp
+++ b/src/tools/wasm2js.cpp
@@ -145,9 +145,20 @@ static void replaceInPlaceIfPossible(Ref target, Ref value) {
static void optimizeJS(Ref ast) {
// Helpers
- auto isOrZero = [](Ref node) {
+ auto isBinary = [](Ref node, IString op) {
return node->isArray() && !node->empty() && node[0] == BINARY &&
- node[1] == OR && node[3]->isNumber() && node[3]->getNumber() == 0;
+ node[1] == op;
+ };
+
+ auto isConstantBinary = [&](Ref node, IString op, int num) {
+ return isBinary(node, op) && node[3]->isNumber() &&
+ node[3]->getNumber() == num;
+ };
+
+ auto isOrZero = [&](Ref node) { return isConstantBinary(node, OR, 0); };
+
+ auto isTrshiftZero = [&](Ref node) {
+ return isConstantBinary(node, TRSHIFT, 0);
};
auto isPlus = [](Ref node) {
@@ -174,11 +185,6 @@ static void optimizeJS(Ref ast) {
node[1] == op;
};
- auto isConstantBitwise = [](Ref node, IString op, int num) {
- return node->isArray() && !node->empty() && node[0] == BINARY &&
- node[1] == op && node[3]->isNumber() && node[3]->getNumber() == num;
- };
-
auto isWhile = [](Ref node) {
return node->isArray() && !node->empty() && node[0] == WHILE;
};
@@ -243,11 +249,14 @@ static void optimizeJS(Ref ast) {
};
auto optimizeBoolean = [&](Ref node) {
- // x ^ 1 => !x
- if (isConstantBitwise(node, XOR, 1)) {
+ if (isConstantBinary(node, XOR, 1)) {
+ // x ^ 1 => !x
node[0]->setString(UNARY_PREFIX);
node[1]->setString(L_NOT);
node[3]->setNull();
+ } else if (isOrZero(node) || isTrshiftZero(node)) {
+ // Just being different from 0 is enough, casts don't matter.
+ return node[2];
}
return node;
};
@@ -257,7 +266,7 @@ static void optimizeJS(Ref ast) {
// Pre-simplification
traversePost(ast, [&](Ref node) {
// x >> 0 => x | 0
- if (isConstantBitwise(node, RSHIFT, 0)) {
+ if (isConstantBinary(node, RSHIFT, 0)) {
node[1]->setString(OR);
}
});
@@ -270,10 +279,7 @@ static void optimizeJS(Ref ast) {
// x | 0 | 0 => x | 0
if (isOrZero(node)) {
if (isBitwise(node[2])) {
- auto child = node[2];
- node[1] = child[1];
- node[2] = child[2];
- node[3] = child[3];
+ replaceInPlace(node, node[2]);
}
}
if (isHeapAccess(node[2])) {
@@ -284,7 +290,7 @@ static void optimizeJS(Ref ast) {
if (isIntegerHeap(heap)) {
replacementHeap = heap;
}
- } else if (isConstantBitwise(node, TRSHIFT, 0)) {
+ } else if (isTrshiftZero(node)) {
// For signed or unsigned loads smaller than 32 bits, doing an | 0
// was safe either way - they aren't in the range an | 0 can affect.
// For >>> 0 however, a negative value would change, so we still
@@ -308,7 +314,7 @@ static void optimizeJS(Ref ast) {
// better performance (perhaps since HEAPU32 is at risk of not being a
// smallint).
if (node[1] == AND) {
- if (isConstantBitwise(node, AND, 1)) {
+ if (isConstantBinary(node, AND, 1)) {
if (heap == HEAPU8) {
setHeapOnAccess(node[2], HEAP8);
} else if (heap == HEAPU16) {
@@ -348,6 +354,21 @@ static void optimizeJS(Ref ast) {
} else if (isUnary(node, L_NOT)) {
node[2] = optimizeBoolean(node[2]);
}
+ // Add/subtract can merge coercions up.
+ else if (isBinary(node, PLUS) || isBinary(node, MINUS)) {
+ auto left = node[2];
+ auto right = node[3];
+ if (isOrZero(left) && isOrZero(right)) {
+ auto op = node[1]->getIString();
+ // Add a coercion on top.
+ node[1]->setString(OR);
+ node[2] = left;
+ node[3] = ValueBuilder::makeNum(0);
+ // Add/subtract the inner uncoerced values.
+ left[1]->setString(op);
+ left[3] = right[2];
+ }
+ }
// Assignment into a heap coerces.
else if (node->isAssign()) {
auto assign = node->asAssign();
@@ -357,12 +378,12 @@ static void optimizeJS(Ref ast) {
if (isIntegerHeap(heap)) {
if (heap == HEAP8 || heap == HEAPU8) {
while (isOrZero(assign->value()) ||
- isConstantBitwise(assign->value(), AND, 255)) {
+ isConstantBinary(assign->value(), AND, 255)) {
assign->value() = assign->value()[2];
}
} else if (heap == HEAP16 || heap == HEAPU16) {
while (isOrZero(assign->value()) ||
- isConstantBitwise(assign->value(), AND, 65535)) {
+ isConstantBinary(assign->value(), AND, 65535)) {
assign->value() = assign->value()[2];
}
} else {