diff options
-rw-r--r-- | src/tools/wasm2js.cpp | 57 | ||||
-rw-r--r-- | test/wasm2js/br_table_temp.2asm.js.opt | 2 | ||||
-rw-r--r-- | test/wasm2js/emscripten.2asm.js | 42 | ||||
-rw-r--r-- | test/wasm2js/emscripten.2asm.js.opt | 42 | ||||
-rw-r--r-- | test/wasm2js/emscripten.wast | 85 |
5 files changed, 209 insertions, 19 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 { diff --git a/test/wasm2js/br_table_temp.2asm.js.opt b/test/wasm2js/br_table_temp.2asm.js.opt index 5620f829f..4633a99e3 100644 --- a/test/wasm2js/br_table_temp.2asm.js.opt +++ b/test/wasm2js/br_table_temp.2asm.js.opt @@ -12662,7 +12662,7 @@ function asmFunc(global, env, buffer) { function $63($0) { $0 = $0 | 0; - if ($0 - 1 | 0) { + if ($0 - 1) { $0 = 9 } else { $0 = 8 diff --git a/test/wasm2js/emscripten.2asm.js b/test/wasm2js/emscripten.2asm.js index 3cbb33a35..6304e9b9d 100644 --- a/test/wasm2js/emscripten.2asm.js +++ b/test/wasm2js/emscripten.2asm.js @@ -90,6 +90,48 @@ function asmFunc(global, env, buffer) { if ((HEAPU8[144 >> 0] | 0) >>> 0 < 3 >>> 0) { bar() } + if ((bools(314159 | 0) | 0) >>> 7 | 0) { + bar() + } + if ((bools(314159 | 0) | 0) >> 8 | 0) { + bar() + } + if (~~Math_fround(getf32()) >>> 0) { + bar() + } + if (~~Math_fround(getf32())) { + bar() + } + if (~~+getf64() >>> 0) { + bar() + } + if (~~+getf64()) { + bar() + } + if (((geti32() | 0) + (geti32() | 0) | 0) + (geti32() | 0) | 0) { + bar() + } + if ((geti32() | 0) + ((geti32() | 0) + (geti32() | 0) | 0) | 0) { + bar() + } + if (((geti32() | 0) + (geti32() | 0) | 0) + ((geti32() | 0) + (geti32() | 0) | 0) | 0) { + bar() + } + if ((((geti32() | 0) + (geti32() | 0) | 0) + ((geti32() | 0) + (geti32() | 0) | 0) | 0) + (((geti32() | 0) + (geti32() | 0) | 0) + ((geti32() | 0) + (geti32() | 0) | 0) | 0) | 0) { + bar() + } + } + + function geti32() { + return geti32() | 0 | 0; + } + + function getf32() { + return Math_fround(Math_fround(getf32())); + } + + function getf64() { + return +(+getf64()); } function __growWasmMemory($0) { diff --git a/test/wasm2js/emscripten.2asm.js.opt b/test/wasm2js/emscripten.2asm.js.opt index 682daaf85..69251d9bb 100644 --- a/test/wasm2js/emscripten.2asm.js.opt +++ b/test/wasm2js/emscripten.2asm.js.opt @@ -83,6 +83,48 @@ function asmFunc(global, env, buffer) { if (HEAPU8[144] < 3) { bar() } + if (bools(314159) >>> 7) { + bar() + } + if (bools(314159) >> 8) { + bar() + } + if (~~getf32()) { + bar() + } + if (~~getf32()) { + bar() + } + if (~~getf64()) { + bar() + } + if (~~getf64()) { + bar() + } + if ((geti32() + geti32() | 0) + geti32()) { + bar() + } + if (geti32() + (geti32() + geti32() | 0)) { + bar() + } + if (geti32() + geti32() + (geti32() + geti32())) { + bar() + } + if (geti32() + geti32() + (geti32() + geti32()) + (geti32() + geti32() + (geti32() + geti32()))) { + bar() + } + } + + function geti32() { + return geti32(); + } + + function getf32() { + return getf32(); + } + + function getf64() { + return getf64(); } function __growWasmMemory($0) { diff --git a/test/wasm2js/emscripten.wast b/test/wasm2js/emscripten.wast index f6ad7aae7..5b1b81507 100644 --- a/test/wasm2js/emscripten.wast +++ b/test/wasm2js/emscripten.wast @@ -110,6 +110,91 @@ (if (i32.lt_u (i32.load8_u (i32.const 144)) (i32.const 3)) (call $bar) ) + (if (i32.shr_u (call $bools (i32.const 314159)) (i32.const 7)) + (call $bar) + ) + (if (i32.shr_s (call $bools (i32.const 314159)) (i32.const 8)) + (call $bar) + ) + (if (i32.trunc_f32_u (call $getf32)) + (call $bar) + ) + (if (i32.trunc_f32_s (call $getf32)) + (call $bar) + ) + (if (i32.trunc_f64_u (call $getf64)) + (call $bar) + ) + (if (i32.trunc_f64_s (call $getf64)) + (call $bar) + ) + (if + (i32.add + (i32.add + (call $geti32) + (call $geti32) + ) + (call $geti32) + ) + (call $bar) + ) + (if + (i32.add + (call $geti32) + (i32.add + (call $geti32) + (call $geti32) + ) + ) + (call $bar) + ) + (if + (i32.add + (i32.add + (call $geti32) + (call $geti32) + ) + (i32.add + (call $geti32) + (call $geti32) + ) + ) + (call $bar) + ) + (if + (i32.add + (i32.add + (i32.add + (call $geti32) + (call $geti32) + ) + (i32.add + (call $geti32) + (call $geti32) + ) + ) + (i32.add + (i32.add + (call $geti32) + (call $geti32) + ) + (i32.add + (call $geti32) + (call $geti32) + ) + ) + ) + (call $bar) + ) + ) + (func $geti32 (result i32) + (call $geti32) + ) + (func $getf32 (result f32) + (call $getf32) + ) + (func $getf64 (result f64) + (call $getf64) ) (func $__growWasmMemory (param $0 i32) (result i32) (grow_memory |