summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ast/bits.h47
-rw-r--r--src/ast/properties.h77
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/OptimizeInstructions.cpp282
-rw-r--r--src/passes/PickLoadSigns.cpp107
-rw-r--r--src/passes/pass.cpp4
-rw-r--r--src/passes/passes.h1
-rw-r--r--test/dynamicLibrary.fromasm5
-rw-r--r--test/dynamicLibrary.fromasm.imprecise5
-rw-r--r--test/emcc_O2_hello_world.fromasm21
-rw-r--r--test/emcc_O2_hello_world.fromasm.imprecise21
-rw-r--r--test/emcc_hello_world.fromasm167
-rw-r--r--test/emcc_hello_world.fromasm.imprecise167
-rw-r--r--test/memorygrowth.fromasm21
-rw-r--r--test/memorygrowth.fromasm.imprecise21
-rw-r--r--test/passes/optimize-instructions.txt648
-rw-r--r--test/passes/optimize-instructions.wast782
-rw-r--r--test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt10
-rw-r--r--test/passes/pick-load-signs.txt263
-rw-r--r--test/passes/pick-load-signs.wast260
20 files changed, 2535 insertions, 375 deletions
diff --git a/src/ast/bits.h b/src/ast/bits.h
new file mode 100644
index 000000000..d88cb5edb
--- /dev/null
+++ b/src/ast/bits.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_ast_bits_h
+#define wasm_ast_bits_h
+
+#include "support/bits.h"
+
+namespace wasm {
+
+struct Bits {
+ // get a mask to keep only the low # of bits
+ static int32_t lowBitMask(int32_t bits) {
+ uint32_t ret = -1;
+ if (bits >= 32) return ret;
+ return ret >> (32 - bits);
+ }
+
+ // checks if the input is a mask of lower bits, i.e., all 1s up to some high bit, and all zeros
+ // from there. returns the number of masked bits, or 0 if this is not such a mask
+ static uint32_t getMaskedBits(uint32_t mask) {
+ if (mask == uint32_t(-1)) return 32; // all the bits
+ if (mask == 0) return 0; // trivially not a mask
+ // otherwise, see if adding one turns this into a 1-bit thing, 00011111 + 1 => 00100000
+ if (PopCount(mask + 1) != 1) return 0;
+ // this is indeed a mask
+ return 32 - CountLeadingZeroes(mask);
+ }
+};
+
+} // namespace wasm
+
+#endif // wasm_ast_bits_h
+
diff --git a/src/ast/properties.h b/src/ast/properties.h
index 9834c73d0..9121deba5 100644
--- a/src/ast/properties.h
+++ b/src/ast/properties.h
@@ -18,6 +18,7 @@
#define wasm_ast_properties_h
#include "wasm.h"
+#include "ast/bits.h"
namespace wasm {
@@ -52,6 +53,82 @@ struct Properties {
default: return false;
}
}
+
+ // Check if an expression is a sign-extend, and if so, returns the value
+ // that is extended, otherwise nullptr
+ static Expression* getSignExtValue(Expression* curr) {
+ if (auto* outer = curr->dynCast<Binary>()) {
+ if (outer->op == ShrSInt32) {
+ if (auto* outerConst = outer->right->dynCast<Const>()) {
+ if (auto* inner = outer->left->dynCast<Binary>()) {
+ if (inner->op == ShlInt32) {
+ if (auto* innerConst = inner->right->dynCast<Const>()) {
+ if (outerConst->value == innerConst->value) {
+ return inner->left;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return nullptr;
+ }
+
+ // gets the size of the sign-extended value
+ static Index getSignExtBits(Expression* curr) {
+ return 32 - curr->cast<Binary>()->right->cast<Const>()->value.geti32();
+ }
+
+ // Check if an expression is almost a sign-extend: perhaps the inner shift
+ // is too large. We can split the shifts in that case, which is sometimes
+ // useful (e.g. if we can remove the signext)
+ static Expression* getAlmostSignExt(Expression* curr) {
+ if (auto* outer = curr->dynCast<Binary>()) {
+ if (outer->op == ShrSInt32) {
+ if (auto* outerConst = outer->right->dynCast<Const>()) {
+ if (auto* inner = outer->left->dynCast<Binary>()) {
+ if (inner->op == ShlInt32) {
+ if (auto* innerConst = inner->right->dynCast<Const>()) {
+ if (outerConst->value.leU(innerConst->value).geti32()) {
+ return inner->left;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return nullptr;
+ }
+
+ // gets the size of the almost sign-extended value, as well as the
+ // extra shifts, if any
+ static Index getAlmostSignExtBits(Expression* curr, Index& extraShifts) {
+ extraShifts = curr->cast<Binary>()->left->cast<Binary>()->right->cast<Const>()->value.geti32() -
+ curr->cast<Binary>()->right->cast<Const>()->value.geti32();
+ return getSignExtBits(curr);
+ }
+
+ // Check if an expression is a zero-extend, and if so, returns the value
+ // that is extended, otherwise nullptr
+ static Expression* getZeroExtValue(Expression* curr) {
+ if (auto* binary = curr->dynCast<Binary>()) {
+ if (binary->op == AndInt32) {
+ if (auto* c = binary->right->dynCast<Const>()) {
+ if (Bits::getMaskedBits(c->value.geti32())) {
+ return binary->right;
+ }
+ }
+ }
+ }
+ return nullptr;
+ }
+
+ // gets the size of the sign-extended value
+ static Index getZeroExtBits(Expression* curr) {
+ return Bits::getMaskedBits(curr->cast<Binary>()->right->cast<Const>()->value.geti32());
+ }
};
} // wasm
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index 9db1c66ae..74f120e85 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -13,6 +13,7 @@ SET(passes_SOURCES
NameManager.cpp
NameList.cpp
OptimizeInstructions.cpp
+ PickLoadSigns.cpp
PostEmscripten.cpp
Precompute.cpp
Print.cpp
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index bb4748a97..79c01dee7 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -166,7 +166,10 @@ struct Match {
// returns the maximum amount of bits used in an integer expression
// not extremely precise (doesn't look into add operands, etc.)
-static Index getMaxBits(Expression* curr) {
+// LocalInfoProvider is an optional class that can provide answers about
+// get_local.
+template<typename LocalInfoProvider>
+Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) {
if (auto* const_ = curr->dynCast<Const>()) {
switch (curr->type) {
case i32: return 32 - const_->value.countLeadingZeroes().geti32();
@@ -179,17 +182,17 @@ static Index getMaxBits(Expression* curr) {
case AddInt32: case SubInt32: case MulInt32:
case DivSInt32: case DivUInt32: case RemSInt32:
case RemUInt32: case RotLInt32: case RotRInt32: return 32;
- case AndInt32: case XorInt32: return std::min(getMaxBits(binary->left), getMaxBits(binary->right));
- case OrInt32: return std::max(getMaxBits(binary->left), getMaxBits(binary->right));
+ case AndInt32: return std::min(getMaxBits(binary->left, localInfoProvider), getMaxBits(binary->right, localInfoProvider));
+ case OrInt32: case XorInt32: return std::max(getMaxBits(binary->left, localInfoProvider), getMaxBits(binary->right, localInfoProvider));
case ShlInt32: {
if (auto* shifts = binary->right->dynCast<Const>()) {
- return std::min(Index(32), getMaxBits(binary->left) + shifts->value.geti32());
+ return std::min(Index(32), getMaxBits(binary->left, localInfoProvider) + shifts->value.geti32());
}
return 32;
}
case ShrUInt32: {
if (auto* shift = binary->right->dynCast<Const>()) {
- auto maxBits = getMaxBits(binary->left);
+ auto maxBits = getMaxBits(binary->left, localInfoProvider);
auto shifts = std::min(Index(shift->value.geti32()), maxBits); // can ignore more shifts than zero us out
return std::max(Index(0), maxBits - shifts);
}
@@ -197,7 +200,7 @@ static Index getMaxBits(Expression* curr) {
}
case ShrSInt32: {
if (auto* shift = binary->right->dynCast<Const>()) {
- auto maxBits = getMaxBits(binary->left);
+ auto maxBits = getMaxBits(binary->left, localInfoProvider);
if (maxBits == 32) return 32;
auto shifts = std::min(Index(shift->value.geti32()), maxBits); // can ignore more shifts than zero us out
return std::max(Index(0), maxBits - shifts);
@@ -225,9 +228,19 @@ static Index getMaxBits(Expression* curr) {
case ClzInt32: case CtzInt32: case PopcntInt32: return 5;
case ClzInt64: case CtzInt64: case PopcntInt64: return 6;
case EqZInt32: case EqZInt64: return 1;
- case WrapInt64: return std::min(Index(32), getMaxBits(unary->value));
+ case WrapInt64: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider));
default: {}
}
+ } else if (auto* set = curr->dynCast<SetLocal>()) {
+ // a tee passes through the value
+ return getMaxBits(set->value, localInfoProvider);
+ } else if (auto* get = curr->dynCast<GetLocal>()) {
+ return localInfoProvider->getMaxBitsForLocal(get);
+ } else if (auto* load = curr->dynCast<Load>()) {
+ // if signed, then the sign-extension might fill all the bits
+ if (!load->signed_) {
+ return 8 * load->bytes;
+ }
}
switch (curr->type) {
case i32: return 32;
@@ -237,68 +250,95 @@ static Index getMaxBits(Expression* curr) {
}
}
-// Check if an expression is a sign-extend, and if so, returns the value
-// that is extended, otherwise nullptr
-static Expression* getSignExt(Expression* curr) {
- if (auto* outer = curr->dynCast<Binary>()) {
- if (outer->op == ShrSInt32) {
- if (auto* outerConst = outer->right->dynCast<Const>()) {
- if (auto* inner = outer->left->dynCast<Binary>()) {
- if (inner->op == ShlInt32) {
- if (auto* innerConst = inner->right->dynCast<Const>()) {
- if (outerConst->value == innerConst->value) {
- return inner->left;
- }
- }
- }
- }
- }
+// looks through fallthrough operations, like tee_local, block fallthrough, etc.
+// too and block fallthroughs, etc.
+Expression* getFallthrough(Expression* curr) {
+ if (auto* set = curr->dynCast<SetLocal>()) {
+ if (set->isTee()) {
+ return getFallthrough(set->value);
+ }
+ } else if (auto* block = curr->dynCast<Block>()) {
+ // if no name, we can't be broken to, and then can look at the fallthrough
+ if (!block->name.is() && block->list.size() > 0) {
+ return getFallthrough(block->list.back());
}
}
- return nullptr;
+ return curr;
}
-// gets the size of the sign-extended value
-static Index getSignExtBits(Expression* curr) {
- return 32 - curr->cast<Binary>()->right->cast<Const>()->value.geti32();
-}
+// Useful information about locals
+struct LocalInfo {
+ static const Index kUnknown = Index(-1);
-// Check if an expression is almost a sign-extend: perhaps the inner shift
-// is too large. We can split the shifts in that case, which is sometimes
-// useful (e.g. if we can remove the signext)
-static Expression* getAlmostSignExt(Expression* curr) {
- if (auto* outer = curr->dynCast<Binary>()) {
- if (outer->op == ShrSInt32) {
- if (auto* outerConst = outer->right->dynCast<Const>()) {
- if (auto* inner = outer->left->dynCast<Binary>()) {
- if (inner->op == ShlInt32) {
- if (auto* innerConst = inner->right->dynCast<Const>()) {
- if (outerConst->value.leU(innerConst->value).geti32()) {
- return inner->left;
- }
- }
- }
- }
+ Index maxBits;
+ Index signExtedBits;
+};
+
+struct LocalScanner : PostWalker<LocalScanner, Visitor<LocalScanner>> {
+ std::vector<LocalInfo>& localInfo;
+
+ LocalScanner(std::vector<LocalInfo>& localInfo) : localInfo(localInfo) {}
+
+ void doWalkFunction(Function* func) {
+ // prepare
+ localInfo.resize(func->getNumLocals());
+ for (Index i = 0; i < func->getNumLocals(); i++) {
+ auto& info = localInfo[i];
+ if (func->isParam(i)) {
+ info.maxBits = getBitsForType(func->getLocalType(i)); // worst-case
+ info.signExtedBits = LocalInfo::kUnknown; // we will never know anything
+ } else {
+ info.maxBits = info.signExtedBits = 0; // we are open to learning
+ }
+ }
+ // walk
+ PostWalker<LocalScanner, Visitor<LocalScanner>>::doWalkFunction(func);
+ // finalize
+ for (Index i = 0; i < func->getNumLocals(); i++) {
+ auto& info = localInfo[i];
+ if (info.signExtedBits == LocalInfo::kUnknown) {
+ info.signExtedBits = 0;
}
}
}
- return nullptr;
-}
-// gets the size of the almost sign-extended value, as well as the
-// extra shifts, if any
-static Index getAlmostSignExtBits(Expression* curr, Index& extraShifts) {
- extraShifts = curr->cast<Binary>()->left->cast<Binary>()->right->cast<Const>()->value.geti32() -
- curr->cast<Binary>()->right->cast<Const>()->value.geti32();
- return getSignExtBits(curr);
-}
+ void visitSetLocal(SetLocal* curr) {
+ auto* func = getFunction();
+ if (func->isParam(curr->index)) return;
+ auto type = getFunction()->getLocalType(curr->index);
+ if (type != i32 && type != i64) return;
+ // an integer var, worth processing
+ auto* value = getFallthrough(curr->value);
+ auto& info = localInfo[curr->index];
+ info.maxBits = std::max(info.maxBits, getMaxBits(value, this));
+ auto signExtBits = LocalInfo::kUnknown;
+ if (Properties::getSignExtValue(value)) {
+ signExtBits = Properties::getSignExtBits(value);
+ } else if (auto* load = value->dynCast<Load>()) {
+ if (load->signed_) {
+ signExtBits = load->bytes * 8;
+ }
+ }
+ if (info.signExtedBits == 0) {
+ info.signExtedBits = signExtBits; // first info we see
+ } else if (info.signExtedBits != signExtBits) {
+ info.signExtedBits = LocalInfo::kUnknown; // contradictory information, give up
+ }
+ }
-// get a mask to keep only the low # of bits
-static int32_t lowBitMask(int32_t bits) {
- uint32_t ret = -1;
- if (bits >= 32) return ret;
- return ret >> (32 - bits);
-}
+ // define this for the templated getMaxBits method. we know nothing here yet about locals, so return the maxes
+ Index getMaxBitsForLocal(GetLocal* get) {
+ return getBitsForType(get->type);
+ }
+
+ Index getBitsForType(WasmType type) {
+ switch (type) {
+ case i32: return 32;
+ case i64: return 64;
+ default: return -1;
+ }
+ }
+};
// Main pass class
struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, UnifiedExpressionVisitor<OptimizeInstructions>>> {
@@ -312,6 +352,16 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
#endif
}
+ void doWalkFunction(Function* func) {
+ // first, scan locals
+ {
+ LocalScanner scanner(localInfo);
+ scanner.walkFunction(func);
+ }
+ // main walk
+ WalkerPass<PostWalker<OptimizeInstructions, UnifiedExpressionVisitor<OptimizeInstructions>>>::doWalkFunction(func);
+ }
+
void visitExpression(Expression* curr) {
// we may be able to apply multiple patterns, one may open opportunities that look deeper NB: patterns must not have cycles
while (1) {
@@ -351,40 +401,63 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
std::swap(binary->left, binary->right);
}
}
- if (auto* ext = getAlmostSignExt(binary)) {
+ if (auto* ext = Properties::getAlmostSignExt(binary)) {
Index extraShifts;
- auto bits = getAlmostSignExtBits(binary, extraShifts);
- auto* load = ext->dynCast<Load>();
- // pattern match a load of 8 bits and a sign extend using a shl of 24 then shr_s of 24 as well, etc.
- if (load && ((load->bytes == 1 && bits == 8) || (load->bytes == 2 && bits == 16))) {
- load->signed_ = true;
- return removeAlmostSignExt(binary);
+ auto bits = Properties::getAlmostSignExtBits(binary, extraShifts);
+ if (auto* load = getFallthrough(ext)->dynCast<Load>()) {
+ // pattern match a load of 8 bits and a sign extend using a shl of 24 then shr_s of 24 as well, etc.
+ if ((load->bytes == 1 && bits == 8) || (load->bytes == 2 && bits == 16)) {
+ // if the value falls through, we can't alter the load, as it might be captured in a tee
+ if (load->signed_ == true || load == ext) {
+ load->signed_ = true;
+ return removeAlmostSignExt(binary);
+ }
+ }
}
// if the sign-extend input cannot have a sign bit, we don't need it
- if (getMaxBits(ext) + extraShifts < bits) {
+ // we also don't need it if it already has an identical-sized sign extend
+ if (getMaxBits(ext, this) + extraShifts < bits || isSignExted(ext, bits)) {
return removeAlmostSignExt(binary);
}
- } else if (binary->op == EqInt32) {
+ } else if (binary->op == EqInt32 || binary->op == NeInt32) {
if (auto* c = binary->right->dynCast<Const>()) {
- if (auto* ext = getSignExt(binary->left)) {
+ if (auto* ext = Properties::getSignExtValue(binary->left)) {
// we are comparing a sign extend to a constant, which means we can use a cheaper zext
- auto bits = getSignExtBits(binary->left);
+ auto bits = Properties::getSignExtBits(binary->left);
binary->left = makeZeroExt(ext, bits);
// the const we compare to only needs the relevant bits
- c->value = c->value.and_(Literal(lowBitMask(bits)));
+ c->value = c->value.and_(Literal(Bits::lowBitMask(bits)));
return binary;
}
- if (c->value.geti32() == 0) {
+ if (binary->op == EqInt32 && c->value.geti32() == 0) {
// equal 0 => eqz
return Builder(*getModule()).makeUnary(EqZInt32, binary->left);
}
- } else if (auto* left = getSignExt(binary->left)) {
- if (auto* right = getSignExt(binary->right)) {
+ } else if (auto* left = Properties::getSignExtValue(binary->left)) {
+ if (auto* right = Properties::getSignExtValue(binary->right)) {
// we are comparing two sign-exts, so we may as well replace both with cheaper zexts
- auto bits = getSignExtBits(binary->left);
+ auto bits = Properties::getSignExtBits(binary->left);
binary->left = makeZeroExt(left, bits);
binary->right = makeZeroExt(right, bits);
return binary;
+ } else if (auto* load = binary->right->dynCast<Load>()) {
+ // we are comparing a load to a sign-ext, we may be able to switch to zext
+ auto leftBits = Properties::getSignExtBits(binary->left);
+ if (load->signed_ && leftBits == load->bytes * 8) {
+ load->signed_ = false;
+ binary->left = makeZeroExt(left, leftBits);
+ return binary;
+ }
+ }
+ } else if (auto* load = binary->left->dynCast<Load>()) {
+ if (auto* right = Properties::getSignExtValue(binary->right)) {
+ // we are comparing a load to a sign-ext, we may be able to switch to zext
+ auto rightBits = Properties::getSignExtBits(binary->right);
+ if (load->signed_ && rightBits == load->bytes * 8) {
+ load->signed_ = false;
+ binary->right = makeZeroExt(right, rightBits);
+ return binary;
+ }
}
}
// note that both left and right may be consts, but then we let precompute compute the constant result
@@ -404,11 +477,13 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
if ((load->bytes == 1 && mask == 0xff) ||
(load->bytes == 2 && mask == 0xffff)) {
load->signed_ = false;
- return load;
+ return binary->left;
+ }
+ } else if (auto maskedBits = Bits::getMaskedBits(mask)) {
+ if (getMaxBits(binary->left, this) <= maskedBits) {
+ // a mask of lower bits is not needed if we are already smaller
+ return binary->left;
}
- } else if (mask == 1 && Properties::emitsBoolean(binary->left)) {
- // (bool) & 1 does not need the outer mask
- return binary->left;
}
}
// the square of some operations can be merged
@@ -468,6 +543,13 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
default: {}
}
}
+ // eqz of a sign extension can be of zero-extension
+ if (auto* ext = Properties::getSignExtValue(unary->value)) {
+ // we are comparing a sign extend to a constant, which means we can use a cheaper zext
+ auto bits = Properties::getSignExtBits(unary->value);
+ unary->value = makeZeroExt(ext, bits);
+ return unary;
+ }
}
} else if (auto* set = curr->dynCast<SetGlobal>()) {
// optimize out a set of a get
@@ -518,6 +600,12 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
}
}
}
+ } else if (auto* ext = Properties::getSignExtValue(binary)) {
+ // if sign extending the exact bit size we store, we can skip the extension
+ // if extending something bigger, then we just alter bits we don't save anyhow
+ if (Properties::getSignExtBits(binary) >= store->bytes * 8) {
+ store->value = ext;
+ }
}
} else if (auto* unary = store->value->dynCast<Unary>()) {
if (unary->op == WrapInt64) {
@@ -530,7 +618,15 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
return nullptr;
}
+ Index getMaxBitsForLocal(GetLocal* get) {
+ // check what we know about the local
+ return localInfo[get->index].maxBits;
+ }
+
private:
+ // Information about our locals
+ std::vector<LocalInfo> localInfo;
+
// Optimize given that the expression is flowing into a boolean context
Expression* optimizeBoolean(Expression* boolean) {
if (auto* unary = boolean->dynCast<Unary>()) {
@@ -554,6 +650,10 @@ private:
}
}
}
+ if (auto* ext = Properties::getSignExtValue(binary)) {
+ // use a cheaper zero-extent, we just care about the boolean value anyhow
+ return makeZeroExt(ext, Properties::getSignExtBits(binary));
+ }
} else if (auto* block = boolean->dynCast<Block>()) {
if (block->type == i32 && block->list.size() > 0) {
block->list.back() = optimizeBoolean(block->list.back());
@@ -611,7 +711,15 @@ private:
};
// find all factors
seek(binary, 1);
- if (constants.size() <= 1) return nullptr; // nothing to do
+ if (constants.size() <= 1) {
+ // nothing much to do, except for the trivial case of adding/subbing a zero
+ if (auto* c = binary->right->dynCast<Const>()) {
+ if (c->value.geti32() == 0) {
+ return binary->left;
+ }
+ }
+ return nullptr;
+ }
// wipe out all constants, we'll replace with a single added one
for (auto* c : constants) {
c->value = Literal(int32_t(0));
@@ -731,7 +839,7 @@ private:
Expression* makeZeroExt(Expression* curr, int32_t bits) {
Builder builder(*getModule());
- return builder.makeBinary(AndInt32, curr, builder.makeConst(Literal(lowBitMask(bits))));
+ return builder.makeBinary(AndInt32, curr, builder.makeConst(Literal(Bits::lowBitMask(bits))));
}
// given an "almost" sign extend - either a proper one, or it
@@ -748,6 +856,18 @@ private:
innerConst->value = innerConst->value.sub(outerConst->value);
return inner;
}
+
+ // check if an expression is already sign-extended
+ bool isSignExted(Expression* curr, Index bits) {
+ if (Properties::getSignExtValue(curr)) {
+ return Properties::getSignExtBits(curr) == bits;
+ }
+ if (auto* get = curr->dynCast<GetLocal>()) {
+ // check what we know about the local
+ return localInfo[get->index].signExtedBits == bits;
+ }
+ return false;
+ }
};
Pass *createOptimizeInstructionsPass() {
diff --git a/src/passes/PickLoadSigns.cpp b/src/passes/PickLoadSigns.cpp
new file mode 100644
index 000000000..6e44fddfe
--- /dev/null
+++ b/src/passes/PickLoadSigns.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <wasm.h>
+#include <pass.h>
+#include <ast/properties.h>
+
+namespace wasm {
+
+// Adjust load signedness based on usage. If a load only has uses that sign or
+// unsign it anyhow, then it could be either, and picking the popular one can
+// help remove the most sign/unsign operations
+// unsigned, then it could be either
+
+struct PickLoadSigns : public WalkerPass<ExpressionStackWalker<PickLoadSigns, Visitor<PickLoadSigns>>> {
+ bool isFunctionParallel() override { return true; }
+
+ Pass* create() override { return new PickLoadSigns; }
+
+ struct Usage {
+ Index signedUsages = 0;
+ Index signedBits;
+ Index unsignedUsages = 0;
+ Index unsignedBits;
+ Index totalUsages = 0;
+ };
+ std::vector<Usage> usages; // local index => usage
+
+ std::unordered_map<Load*, Index> loads; // loads that write to a local => the local
+
+ void doWalkFunction(Function* func) {
+ // prepare
+ usages.resize(func->getNumLocals());
+ // walk
+ ExpressionStackWalker<PickLoadSigns, Visitor<PickLoadSigns>>::doWalkFunction(func);
+ // optimize based on the info we saw
+ for (auto& pair : loads) {
+ auto* load = pair.first;
+ auto index = pair.second;
+ auto& usage = usages[index];
+ // if we can't optimize, give up
+ if (usage.totalUsages == 0 || // no usages, so no idea
+ usage.signedUsages + usage.unsignedUsages != usage.totalUsages || // non-sign/unsigned usages, so cannot change
+ (usage.signedUsages != 0 && usage.signedBits != load->bytes * 8) || // sign usages exist but the wrong size
+ (usage.unsignedUsages != 0 && usage.unsignedBits != load->bytes * 8)) { // unsigned usages exist but the wrong size
+ continue;
+ }
+ // we can pick the optimal one. our hope is to remove 2 items per
+ // signed use (two shifts), so we factor that in
+ load->signed_ = usage.signedUsages * 2 >= usage.unsignedUsages;
+ }
+ }
+
+ void visitGetLocal(GetLocal* curr) {
+ // this is a use. check from the context what it is, signed or unsigned, etc.
+ auto& usage = usages[curr->index];
+ usage.totalUsages++;
+ if (expressionStack.size() >= 2) {
+ auto* parent = expressionStack[expressionStack.size() - 2];
+ if (Properties::getZeroExtValue(parent)) {
+ auto bits = Properties::getZeroExtBits(parent);
+ if (usage.unsignedUsages == 0) {
+ usage.unsignedBits = bits;
+ } else if (usage.unsignedBits != bits) {
+ usage.unsignedBits = 0;
+ }
+ usage.unsignedUsages++;
+ } else if (expressionStack.size() >= 3) {
+ auto* grandparent = expressionStack[expressionStack.size() - 3];
+ if (Properties::getSignExtValue(grandparent)) {
+ auto bits = Properties::getSignExtBits(grandparent);
+ if (usage.signedUsages == 0) {
+ usage.signedBits = bits;
+ } else if (usage.signedBits != bits) {
+ usage.signedBits = 0;
+ }
+ usage.signedUsages++;
+ }
+ }
+ }
+ }
+
+ void visitSetLocal(SetLocal* curr) {
+ if (auto* load = curr->value->dynCast<Load>()) {
+ loads[load] = curr->index;
+ }
+ }
+};
+
+Pass *createPickLoadSignsPass() {
+ return new PickLoadSigns();
+}
+
+} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 32b596eef..df98590c5 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -77,6 +77,7 @@ void PassRegistry::registerPasses() {
registerPass("nm", "name list", createNameListPass);
registerPass("name-manager", "utility pass to manage names in modules", createNameManagerPass);
registerPass("optimize-instructions", "optimizes instruction combinations", createOptimizeInstructionsPass);
+ registerPass("pick-load-signs", "pick load signs based on their uses", createPickLoadSignsPass);
registerPass("post-emscripten", "miscellaneous optimizations for Emscripten-generated code", createPostEmscriptenPass);
registerPass("print", "print in s-expression format", createPrinterPass);
registerPass("print-minified", "print in minified s-expression format", createMinifiedPrinterPass);
@@ -112,6 +113,9 @@ void PassRunner::addDefaultFunctionOptimizationPasses() {
add("remove-unused-brs");
add("remove-unused-names");
add("optimize-instructions");
+ if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) {
+ add("pick-load-signs");
+ }
add("precompute");
if (options.optimizeLevel >= 2 || options.shrinkLevel >= 2) {
add("code-pushing");
diff --git a/src/passes/passes.h b/src/passes/passes.h
index cbfc48327..83bf556d8 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -39,6 +39,7 @@ Pass *createMetricsPass();
Pass *createNameListPass();
Pass *createNameManagerPass();
Pass *createOptimizeInstructionsPass();
+Pass *createPickLoadSignsPass();
Pass *createPostEmscriptenPass();
Pass *createPrinterPass();
Pass *createPrintCallGraphPass();
diff --git a/test/dynamicLibrary.fromasm b/test/dynamicLibrary.fromasm
index df7825187..68cea0677 100644
--- a/test/dynamicLibrary.fromasm
+++ b/test/dynamicLibrary.fromasm
@@ -45,10 +45,7 @@
)
(drop
(call $_puts
- (i32.add
- (get_global $memoryBase)
- (i32.const 0)
- )
+ (get_global $memoryBase)
)
)
(set_global $STACKTOP
diff --git a/test/dynamicLibrary.fromasm.imprecise b/test/dynamicLibrary.fromasm.imprecise
index 357d324cd..0c656a8e6 100644
--- a/test/dynamicLibrary.fromasm.imprecise
+++ b/test/dynamicLibrary.fromasm.imprecise
@@ -44,10 +44,7 @@
)
(drop
(call $_puts
- (i32.add
- (get_global $memoryBase)
- (i32.const 0)
- )
+ (get_global $memoryBase)
)
)
(set_global $STACKTOP
diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm
index 5aa32979b..f885bf5b8 100644
--- a/test/emcc_O2_hello_world.fromasm
+++ b/test/emcc_O2_hello_world.fromasm
@@ -8555,15 +8555,9 @@
)
)
(if
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
- (i32.const 24)
- )
- (i32.const 24)
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
(block
(set_local $1
@@ -9684,12 +9678,9 @@
(func $dynCall_ii (param $0 i32) (param $1 i32) (result i32)
(call_indirect $FUNCSIG$ii
(get_local $1)
- (i32.add
- (i32.and
- (get_local $0)
- (i32.const 1)
- )
- (i32.const 0)
+ (i32.and
+ (get_local $0)
+ (i32.const 1)
)
)
)
diff --git a/test/emcc_O2_hello_world.fromasm.imprecise b/test/emcc_O2_hello_world.fromasm.imprecise
index 39ed6731f..d0d86a165 100644
--- a/test/emcc_O2_hello_world.fromasm.imprecise
+++ b/test/emcc_O2_hello_world.fromasm.imprecise
@@ -8554,15 +8554,9 @@
)
)
(if
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
- (i32.const 24)
- )
- (i32.const 24)
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
(block
(set_local $1
@@ -9673,12 +9667,9 @@
(func $dynCall_ii (param $0 i32) (param $1 i32) (result i32)
(call_indirect $FUNCSIG$ii
(get_local $1)
- (i32.add
- (i32.and
- (get_local $0)
- (i32.const 1)
- )
- (i32.const 0)
+ (i32.and
+ (get_local $0)
+ (i32.const 1)
)
)
)
diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm
index 71ce805ba..ecbadd304 100644
--- a/test/emcc_hello_world.fromasm
+++ b/test/emcc_hello_world.fromasm
@@ -174,28 +174,25 @@
(block $switch-case0
(block $switch-case
(br_table $switch-case $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case0 $switch-default
- (i32.sub
- (tee_local $3
- (i32.and
- (tee_local $3
- (call $_bitshift64Lshr
- (tee_local $2
- (i32.load
- (get_global $tempDoublePtr)
- )
+ (tee_local $3
+ (i32.and
+ (tee_local $3
+ (call $_bitshift64Lshr
+ (tee_local $2
+ (i32.load
+ (get_global $tempDoublePtr)
)
- (tee_local $4
- (i32.load offset=4
- (get_global $tempDoublePtr)
- )
+ )
+ (tee_local $4
+ (i32.load offset=4
+ (get_global $tempDoublePtr)
)
- (i32.const 52)
)
+ (i32.const 52)
)
- (i32.const 2047)
)
+ (i32.const 2047)
)
- (i32.const 0)
)
)
)
@@ -328,7 +325,7 @@
)
)
(if
- (i32.load8_u
+ (i32.load8_s
(get_local $0)
)
(block
@@ -1471,7 +1468,7 @@
)
(if
(i32.ne
- (i32.load8_u
+ (i32.load8_s
(i32.add
(get_local $0)
(tee_local $6
@@ -1944,14 +1941,11 @@
(i32.load8_u
(get_local $2)
)
- (i32.and
- (tee_local $1
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
+ (tee_local $1
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
- (i32.const 255)
)
)
(block
@@ -2504,13 +2498,10 @@
)
(br_if $__rjti$9
(i32.eqz
- (i32.and
- (tee_local $7
- (i32.load8_s
- (get_local $5)
- )
+ (tee_local $7
+ (i32.load8_s
+ (get_local $5)
)
- (i32.const 255)
)
)
)
@@ -2525,15 +2516,12 @@
(block $switch-case0
(block $switch-case
(br_table $switch-case0 $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case $switch-default
- (i32.sub
- (i32.shr_s
- (i32.shl
- (get_local $7)
- (i32.const 24)
- )
+ (i32.shr_s
+ (i32.shl
+ (get_local $7)
(i32.const 24)
)
- (i32.const 0)
+ (i32.const 24)
)
)
)
@@ -2565,7 +2553,7 @@
(loop $while-in
(br_if $label$break$L12
(i32.ne
- (i32.load8_u offset=1
+ (i32.load8_s offset=1
(get_local $6)
)
(i32.const 37)
@@ -2579,7 +2567,7 @@
)
(br_if $while-in
(i32.eq
- (i32.load8_u
+ (i32.load8_s
(tee_local $6
(i32.add
(get_local $6)
@@ -2638,21 +2626,15 @@
(i32.lt_u
(tee_local $8
(i32.add
- (i32.shr_s
- (i32.shl
- (tee_local $11
- (i32.load8_s
- (tee_local $10
- (i32.add
- (get_local $6)
- (i32.const 1)
- )
- )
+ (tee_local $11
+ (i32.load8_s
+ (tee_local $10
+ (i32.add
+ (get_local $6)
+ (i32.const 1)
)
)
- (i32.const 24)
)
- (i32.const 24)
)
(i32.const -48)
)
@@ -2671,7 +2653,7 @@
(get_local $10)
(tee_local $11
(i32.eq
- (i32.load8_u offset=2
+ (i32.load8_s offset=2
(get_local $6)
)
(i32.const 36)
@@ -2778,21 +2760,15 @@
(i32.eq
(i32.and
(tee_local $6
- (i32.shr_s
- (i32.shl
- (tee_local $1
- (i32.load8_s
- (tee_local $10
- (i32.add
- (get_local $10)
- (i32.const 1)
- )
- )
+ (tee_local $1
+ (i32.load8_s
+ (tee_local $10
+ (i32.add
+ (get_local $10)
+ (i32.const 1)
)
)
- (i32.const 24)
)
- (i32.const 24)
)
)
(i32.const -32)
@@ -2846,7 +2822,7 @@
)
(br_if $__rjti$0
(i32.ne
- (i32.load8_u offset=2
+ (i32.load8_s offset=2
(get_local $10)
)
(i32.const 36)
@@ -3078,7 +3054,7 @@
(set_local $6
(if i32
(i32.eq
- (i32.load8_u
+ (i32.load8_s
(get_local $10)
)
(i32.const 46)
@@ -3086,18 +3062,15 @@
(block i32
(if
(i32.ne
- (i32.and
- (tee_local $8
- (i32.load8_s
- (tee_local $6
- (i32.add
- (get_local $10)
- (i32.const 1)
- )
+ (tee_local $8
+ (i32.load8_s
+ (tee_local $6
+ (i32.add
+ (get_local $10)
+ (i32.const 1)
)
)
)
- (i32.const 255)
)
(i32.const 42)
)
@@ -3106,13 +3079,7 @@
(i32.lt_u
(tee_local $9
(i32.add
- (i32.shr_s
- (i32.shl
- (get_local $8)
- (i32.const 24)
- )
- (i32.const 24)
- )
+ (get_local $8)
(i32.const -48)
)
)
@@ -3196,7 +3163,7 @@
)
(if
(i32.eq
- (i32.load8_u offset=3
+ (i32.load8_s offset=3
(get_local $10)
)
(i32.const 36)
@@ -3557,10 +3524,7 @@
(block $switch-case20
(block $switch-case19
(br_table $switch-case19 $switch-case20 $switch-case21 $switch-case22 $switch-case23 $switch-default26 $switch-case24 $switch-case25 $switch-default26
- (i32.sub
- (get_local $9)
- (i32.const 0)
- )
+ (get_local $9)
)
)
(i32.store
@@ -4225,7 +4189,7 @@
)
(if f64
(i32.eq
- (i32.load8_u
+ (i32.load8_s
(get_local $9)
)
(i32.const 45)
@@ -5285,7 +5249,7 @@
(block
(br_if $do-once83
(i32.ne
- (i32.load8_u
+ (i32.load8_s
(get_local $31)
)
(i32.const 45)
@@ -5531,10 +5495,7 @@
(tee_local $5
(i32.add
(i32.xor
- (i32.and
- (get_local $32)
- (i32.const 1)
- )
+ (get_local $32)
(i32.const 1)
)
(get_local $17)
@@ -9414,13 +9375,10 @@
(i32.shl
(get_local $8)
(i32.xor
- (i32.and
- (tee_local $6
- (i32.eqz
- (get_local $9)
- )
+ (tee_local $6
+ (i32.eqz
+ (get_local $9)
)
- (i32.const 1)
)
(i32.const 1)
)
@@ -15761,12 +15719,9 @@
(func $dynCall_ii (param $0 i32) (param $1 i32) (result i32)
(call_indirect $FUNCSIG$ii
(get_local $1)
- (i32.add
- (i32.and
- (get_local $0)
- (i32.const 1)
- )
- (i32.const 0)
+ (i32.and
+ (get_local $0)
+ (i32.const 1)
)
)
)
diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise
index 58dc7b313..52fa498da 100644
--- a/test/emcc_hello_world.fromasm.imprecise
+++ b/test/emcc_hello_world.fromasm.imprecise
@@ -171,28 +171,25 @@
(block $switch-case0
(block $switch-case
(br_table $switch-case $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case0 $switch-default
- (i32.sub
- (tee_local $3
- (i32.and
- (tee_local $3
- (call $_bitshift64Lshr
- (tee_local $2
- (i32.load
- (get_global $tempDoublePtr)
- )
+ (tee_local $3
+ (i32.and
+ (tee_local $3
+ (call $_bitshift64Lshr
+ (tee_local $2
+ (i32.load
+ (get_global $tempDoublePtr)
)
- (tee_local $4
- (i32.load offset=4
- (get_global $tempDoublePtr)
- )
+ )
+ (tee_local $4
+ (i32.load offset=4
+ (get_global $tempDoublePtr)
)
- (i32.const 52)
)
+ (i32.const 52)
)
- (i32.const 2047)
)
+ (i32.const 2047)
)
- (i32.const 0)
)
)
)
@@ -325,7 +322,7 @@
)
)
(if
- (i32.load8_u
+ (i32.load8_s
(get_local $0)
)
(block
@@ -1468,7 +1465,7 @@
)
(if
(i32.ne
- (i32.load8_u
+ (i32.load8_s
(i32.add
(get_local $0)
(tee_local $6
@@ -1941,14 +1938,11 @@
(i32.load8_u
(get_local $2)
)
- (i32.and
- (tee_local $1
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
+ (tee_local $1
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
- (i32.const 255)
)
)
(block
@@ -2447,13 +2441,10 @@
)
(br_if $__rjti$9
(i32.eqz
- (i32.and
- (tee_local $7
- (i32.load8_s
- (get_local $5)
- )
+ (tee_local $7
+ (i32.load8_s
+ (get_local $5)
)
- (i32.const 255)
)
)
)
@@ -2468,15 +2459,12 @@
(block $switch-case0
(block $switch-case
(br_table $switch-case0 $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-default $switch-case $switch-default
- (i32.sub
- (i32.shr_s
- (i32.shl
- (get_local $7)
- (i32.const 24)
- )
+ (i32.shr_s
+ (i32.shl
+ (get_local $7)
(i32.const 24)
)
- (i32.const 0)
+ (i32.const 24)
)
)
)
@@ -2508,7 +2496,7 @@
(loop $while-in
(br_if $label$break$L12
(i32.ne
- (i32.load8_u offset=1
+ (i32.load8_s offset=1
(get_local $6)
)
(i32.const 37)
@@ -2522,7 +2510,7 @@
)
(br_if $while-in
(i32.eq
- (i32.load8_u
+ (i32.load8_s
(tee_local $6
(i32.add
(get_local $6)
@@ -2581,21 +2569,15 @@
(i32.lt_u
(tee_local $8
(i32.add
- (i32.shr_s
- (i32.shl
- (tee_local $11
- (i32.load8_s
- (tee_local $10
- (i32.add
- (get_local $6)
- (i32.const 1)
- )
- )
+ (tee_local $11
+ (i32.load8_s
+ (tee_local $10
+ (i32.add
+ (get_local $6)
+ (i32.const 1)
)
)
- (i32.const 24)
)
- (i32.const 24)
)
(i32.const -48)
)
@@ -2614,7 +2596,7 @@
(get_local $10)
(tee_local $11
(i32.eq
- (i32.load8_u offset=2
+ (i32.load8_s offset=2
(get_local $6)
)
(i32.const 36)
@@ -2721,21 +2703,15 @@
(i32.eq
(i32.and
(tee_local $6
- (i32.shr_s
- (i32.shl
- (tee_local $1
- (i32.load8_s
- (tee_local $10
- (i32.add
- (get_local $10)
- (i32.const 1)
- )
- )
+ (tee_local $1
+ (i32.load8_s
+ (tee_local $10
+ (i32.add
+ (get_local $10)
+ (i32.const 1)
)
)
- (i32.const 24)
)
- (i32.const 24)
)
)
(i32.const -32)
@@ -2789,7 +2765,7 @@
)
(br_if $__rjti$0
(i32.ne
- (i32.load8_u offset=2
+ (i32.load8_s offset=2
(get_local $10)
)
(i32.const 36)
@@ -3021,7 +2997,7 @@
(set_local $6
(if i32
(i32.eq
- (i32.load8_u
+ (i32.load8_s
(get_local $10)
)
(i32.const 46)
@@ -3029,18 +3005,15 @@
(block i32
(if
(i32.ne
- (i32.and
- (tee_local $8
- (i32.load8_s
- (tee_local $6
- (i32.add
- (get_local $10)
- (i32.const 1)
- )
+ (tee_local $8
+ (i32.load8_s
+ (tee_local $6
+ (i32.add
+ (get_local $10)
+ (i32.const 1)
)
)
)
- (i32.const 255)
)
(i32.const 42)
)
@@ -3049,13 +3022,7 @@
(i32.lt_u
(tee_local $9
(i32.add
- (i32.shr_s
- (i32.shl
- (get_local $8)
- (i32.const 24)
- )
- (i32.const 24)
- )
+ (get_local $8)
(i32.const -48)
)
)
@@ -3139,7 +3106,7 @@
)
(if
(i32.eq
- (i32.load8_u offset=3
+ (i32.load8_s offset=3
(get_local $10)
)
(i32.const 36)
@@ -3500,10 +3467,7 @@
(block $switch-case20
(block $switch-case19
(br_table $switch-case19 $switch-case20 $switch-case21 $switch-case22 $switch-case23 $switch-default26 $switch-case24 $switch-case25 $switch-default26
- (i32.sub
- (get_local $9)
- (i32.const 0)
- )
+ (get_local $9)
)
)
(i32.store
@@ -4186,7 +4150,7 @@
(get_local $15)
)
(i32.eq
- (i32.load8_u
+ (i32.load8_s
(get_local $9)
)
(i32.const 45)
@@ -5222,7 +5186,7 @@
(block
(br_if $do-once83
(i32.ne
- (i32.load8_u
+ (i32.load8_s
(get_local $31)
)
(i32.const 45)
@@ -5468,10 +5432,7 @@
(tee_local $5
(i32.add
(i32.xor
- (i32.and
- (get_local $32)
- (i32.const 1)
- )
+ (get_local $32)
(i32.const 1)
)
(get_local $17)
@@ -9351,13 +9312,10 @@
(i32.shl
(get_local $8)
(i32.xor
- (i32.and
- (tee_local $6
- (i32.eqz
- (get_local $9)
- )
+ (tee_local $6
+ (i32.eqz
+ (get_local $9)
)
- (i32.const 1)
)
(i32.const 1)
)
@@ -15697,12 +15655,9 @@
(func $dynCall_ii (param $0 i32) (param $1 i32) (result i32)
(call_indirect $FUNCSIG$ii
(get_local $1)
- (i32.add
- (i32.and
- (get_local $0)
- (i32.const 1)
- )
- (i32.const 0)
+ (i32.and
+ (get_local $0)
+ (i32.const 1)
)
)
)
diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm
index ef7dc1a78..4a3a60955 100644
--- a/test/memorygrowth.fromasm
+++ b/test/memorygrowth.fromasm
@@ -8474,15 +8474,9 @@
)
)
(if
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
- (i32.const 24)
- )
- (i32.const 24)
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
(block
(set_local $1
@@ -9752,12 +9746,9 @@
(func $kb (param $0 i32) (param $1 i32) (result i32)
(call_indirect $FUNCSIG$ii
(get_local $1)
- (i32.add
- (i32.and
- (get_local $0)
- (i32.const 1)
- )
- (i32.const 0)
+ (i32.and
+ (get_local $0)
+ (i32.const 1)
)
)
)
diff --git a/test/memorygrowth.fromasm.imprecise b/test/memorygrowth.fromasm.imprecise
index 2a32f7528..46ec796a5 100644
--- a/test/memorygrowth.fromasm.imprecise
+++ b/test/memorygrowth.fromasm.imprecise
@@ -8473,15 +8473,9 @@
)
)
(if
- (i32.shr_s
- (i32.shl
- (i32.and
- (get_local $1)
- (i32.const 255)
- )
- (i32.const 24)
- )
- (i32.const 24)
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
)
(block
(set_local $1
@@ -9741,12 +9735,9 @@
(func $kb (param $0 i32) (param $1 i32) (result i32)
(call_indirect $FUNCSIG$ii
(get_local $1)
- (i32.add
- (i32.and
- (get_local $0)
- (i32.const 1)
- )
- (i32.const 0)
+ (i32.and
+ (get_local $0)
+ (i32.const 1)
)
)
)
diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt
index 03f0f7074..d70e6a9c5 100644
--- a/test/passes/optimize-instructions.txt
+++ b/test/passes/optimize-instructions.txt
@@ -4,6 +4,7 @@
(type $2 (func (result i32)))
(type $3 (func (param i32) (result i32)))
(type $4 (func (param i32 i32)))
+ (type $5 (func (param i32)))
(memory $0 0)
(export "load-off-2" (func $load-off-2))
(func $f (type $0) (param $i1 i32) (param $i2 i64)
@@ -668,15 +669,15 @@
(drop
(i32.xor
(i32.const 127)
- (i32.const 128)
+ (i32.const 126)
)
)
(drop
(i32.shr_s
(i32.shl
(i32.xor
+ (i32.const 127)
(i32.const 128)
- (i32.const 129)
)
(i32.const 24)
)
@@ -913,6 +914,21 @@
(i32.const 25)
)
)
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (i32.xor
+ (i32.le_u
+ (get_local $0)
+ (i32.const 2)
+ )
+ (get_local $0)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
)
(func $linear-sums (type $4) (param $0 i32) (param $1 i32)
(drop
@@ -1079,4 +1095,632 @@
)
)
)
+ (func $sign-ext-ne (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (i32.ne
+ (i32.and
+ (get_local $0)
+ (i32.const 255)
+ )
+ (i32.const 232)
+ )
+ )
+ (drop
+ (i32.ne
+ (i32.and
+ (get_local $0)
+ (i32.const 255)
+ )
+ (i32.const 111)
+ )
+ )
+ (drop
+ (i32.ne
+ (i32.and
+ (get_local $0)
+ (i32.const 255)
+ )
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
+ )
+ )
+ )
+ )
+ (func $sign-ext-eqz (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (i32.eqz
+ (i32.and
+ (get_local $0)
+ (i32.const 255)
+ )
+ )
+ )
+ )
+ (func $sign-ext-boolean (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (if i32
+ (i32.and
+ (get_local $0)
+ (i32.const 255)
+ )
+ (i32.const 100)
+ (i32.const 200)
+ )
+ )
+ )
+ (func $add-sub-zero (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (get_local $0)
+ )
+ (drop
+ (get_local $0)
+ )
+ )
+ (func $store-signext (type $5) (param $0 i32)
+ (i32.store8
+ (i32.const 8)
+ (get_local $0)
+ )
+ (i32.store8
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 25)
+ )
+ (i32.const 25)
+ )
+ )
+ (i32.store8
+ (i32.const 8)
+ (get_local $0)
+ )
+ (i32.store16
+ (i32.const 8)
+ (get_local $0)
+ )
+ (i32.store16
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 17)
+ )
+ (i32.const 17)
+ )
+ )
+ (i32.store16
+ (i32.const 8)
+ (get_local $0)
+ )
+ (i32.store
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ (i32.store
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 8)
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (func $sign-ext-tee (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (tee_local $0
+ (i32.const 127)
+ )
+ )
+ )
+ (func $sign-ext-load (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (i32.load8_s
+ (i32.const 256)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (i32.shr_u
+ (i32.load8_s
+ (i32.const 256)
+ )
+ (i32.const 1)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_u
+ (i32.load8_u
+ (i32.const 256)
+ )
+ (i32.const 1)
+ )
+ )
+ (drop
+ (i32.load16_s
+ (i32.const 256)
+ )
+ )
+ (drop
+ (tee_local $1
+ (i32.load8_s
+ (i32.const 1)
+ )
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (tee_local $1
+ (i32.load8_u
+ (i32.const 1)
+ )
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $1
+ (i32.load8_s
+ (i32.const 1)
+ )
+ )
+ (i32.const 255)
+ )
+ )
+ (drop
+ (tee_local $1
+ (i32.load8_u
+ (i32.const 1)
+ )
+ )
+ )
+ )
+ (func $mask-bits (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (tee_local $0
+ (i32.const 127)
+ )
+ )
+ (drop
+ (tee_local $0
+ (i32.const 128)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 254)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1279)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1290)
+ )
+ )
+ (drop
+ (tee_local $0
+ (i32.const 128)
+ )
+ )
+ (drop
+ (tee_local $0
+ (i32.const 128)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 127)
+ )
+ )
+ )
+ (func $local-info-zero-ext (type $4) (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.const 212)
+ )
+ (drop
+ (get_local $x)
+ )
+ (set_local $y
+ (i32.const 500)
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (set_local $0
+ (i32.const 212)
+ )
+ (drop
+ (i32.and
+ (get_local $0)
+ (i32.const 255)
+ )
+ )
+ (set_local $z
+ (i32.const 212)
+ )
+ (set_local $z
+ (i32.const 220)
+ )
+ (drop
+ (get_local $z)
+ )
+ (set_local $w
+ (i32.const 212)
+ )
+ (set_local $w
+ (i32.const 1000)
+ )
+ (drop
+ (i32.and
+ (get_local $w)
+ (i32.const 255)
+ )
+ )
+ )
+ (func $local-info-sign-ext-bitsize (type $4) (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.const 127)
+ )
+ (drop
+ (get_local $x)
+ )
+ (set_local $y
+ (i32.const 128)
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $0
+ (i32.const 127)
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.const 127)
+ )
+ (set_local $z
+ (i32.const 100)
+ )
+ (drop
+ (get_local $z)
+ )
+ (set_local $w
+ (i32.const 127)
+ )
+ (set_local $w
+ (i32.const 150)
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $w)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $local-info-sign-ext-already-exted (type $4) (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (get_local $x)
+ )
+ (set_local $y
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $0
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (get_local $z)
+ )
+ (set_local $w
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $w
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 23)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $w)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 23)
+ )
+ )
+ )
+ (func $signed-loads-fill-the-bits (type $3) (param $$e i32) (result i32)
+ (local $$0 i32)
+ (local $$conv i32)
+ (set_local $$0
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (set_local $$conv
+ (i32.and
+ (get_local $$0)
+ (i32.const 255)
+ )
+ )
+ (return
+ (i32.eq
+ (get_local $$conv)
+ (get_local $$e)
+ )
+ )
+ )
+ (func $local-info-sign-ext-already-exted-by-load (type $4) (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (get_local $x)
+ )
+ (set_local $y
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.load16_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $z)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $compare-load-s-sign-extend (type $4) (param $0 i32) (param $1 i32)
+ (drop
+ (i32.eq
+ (i32.load8_u
+ (get_local $0)
+ )
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.and
+ (get_local $1)
+ (i32.const 255)
+ )
+ (i32.load8_u
+ (get_local $0)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.load8_u
+ (get_local $0)
+ )
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.load8_s
+ (get_local $0)
+ )
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.load8_u
+ (get_local $0)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ (i32.load8_s
+ (get_local $0)
+ )
+ )
+ )
+ )
)
diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast
index c59bb3ade..51bd076d1 100644
--- a/test/passes/optimize-instructions.wast
+++ b/test/passes/optimize-instructions.wast
@@ -654,9 +654,9 @@
(drop
(i32.shr_s
(i32.shl
- (i32.xor ;; takes the min, here it is ok
+ (i32.xor ;; takes the max, here it is ok
(i32.const 127)
- (i32.const 128)
+ (i32.const 126)
)
(i32.const 24)
)
@@ -666,9 +666,9 @@
(drop
(i32.shr_s
(i32.shl
- (i32.xor ;; takes the min, here it is not
+ (i32.xor ;; takes the max, here it is not
+ (i32.const 127)
(i32.const 128)
- (i32.const 129)
)
(i32.const 24)
)
@@ -1013,6 +1013,21 @@
(i32.const 24)
)
)
+ (drop ;; fuzz testcase
+ (i32.shr_s
+ (i32.shl
+ (i32.xor ;; should be 32 bits
+ (i32.le_u ;; 1 bit
+ (get_local $0)
+ (i32.const 2)
+ )
+ (get_local $0) ;; unknown, so 32 bits
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
)
(func $linear-sums (param $0 i32) (param $1 i32)
(drop
@@ -1332,4 +1347,763 @@
)
)
)
+ (func $sign-ext-ne (param $0 i32) (param $1 i32)
+ ;; ne of sign-ext to const, can be a zext
+ (drop
+ (i32.ne
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.const 65000)
+ )
+ )
+ (drop
+ (i32.ne
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.const 111)
+ )
+ )
+ (drop
+ (i32.ne
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (func $sign-ext-eqz (param $0 i32) (param $1 i32)
+ (drop
+ (i32.eqz
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ )
+ (func $sign-ext-boolean (param $0 i32) (param $1 i32)
+ (drop
+ (if i32
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.const 100)
+ (i32.const 200)
+ )
+ )
+ )
+ (func $add-sub-zero (param $0 i32) (param $1 i32)
+ (drop
+ (i32.add
+ (get_local $0)
+ (i32.const 0)
+ )
+ )
+ (drop
+ (i32.sub
+ (get_local $0)
+ (i32.const 0)
+ )
+ )
+ )
+ (func $store-signext (param $0 i32)
+ (i32.store8
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24) ;; exact size we store, sign-ext of 8 bits
+ )
+ (i32.const 24)
+ )
+ )
+ (i32.store8
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 25) ;; 7 bits. so the ext can alter a bit we store, do not optimize
+ )
+ (i32.const 25)
+ )
+ )
+ (i32.store8
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 23) ;; 9 bits, this is good to optimize
+ )
+ (i32.const 23)
+ )
+ )
+ (i32.store16
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 16) ;; exact size we store, sign-ext of 16 bits
+ )
+ (i32.const 16)
+ )
+ )
+ (i32.store16
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 17) ;; 15 bits. so the ext can alter a bit we store, do not optimize
+ )
+ (i32.const 17)
+ )
+ )
+ (i32.store16
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 14) ;; 17 bits, this is good to optimize
+ )
+ (i32.const 14)
+ )
+ )
+ (i32.store
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 16) ;; 4 bytes stored, do nothing
+ )
+ (i32.const 16)
+ )
+ )
+ (i32.store
+ (i32.const 8)
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 8) ;; 4 bytes stored, do nothing
+ )
+ (i32.const 8)
+ )
+ )
+ )
+ (func $sign-ext-tee (param $0 i32) (param $1 i32)
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (tee_local $0
+ (i32.const 128) ;; too big
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (tee_local $0
+ (i32.const 127) ;; just right
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $sign-ext-load (param $0 i32) (param $1 i32)
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (i32.load8_s ;; one byte, so perfect
+ (i32.const 256)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (i32.shr_u
+ (i32.load8_s ;; one byte, but sexted to 32
+ (i32.const 256)
+ )
+ (i32.const 1)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (i32.shr_u
+ (i32.load8_u ;; one byte, but reduced to 7
+ (i32.const 256)
+ )
+ (i32.const 1)
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (i32.load16_s ;; two, so perfect
+ (i32.const 256)
+ )
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ ;; through tees, we cannot alter the load sign
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (tee_local $1
+ (i32.load8_s
+ (i32.const 1)
+ )
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (tee_local $1
+ (i32.load8_u
+ (i32.const 1)
+ )
+ )
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $1
+ (i32.load8_s
+ (i32.const 1)
+ )
+ )
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $1
+ (i32.load8_u
+ (i32.const 1)
+ )
+ )
+ (i32.const 255)
+ )
+ )
+ )
+ (func $mask-bits (param $0 i32) (param $1 i32)
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 127) ;; 7 bits
+ )
+ (i32.const 255) ;; mask 8, so we don't need this
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128) ;; 8 bits
+ )
+ (i32.const 255) ;; mask 8, so we don't need this
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 254) ;; improper mask, small
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1279) ;; improper mask, large
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 1290) ;; improper mask, large
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 4095) ;; proper mask, huge
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 511) ;; proper mask, large
+ )
+ )
+ (drop
+ (i32.and
+ (tee_local $0
+ (i32.const 128)
+ )
+ (i32.const 127) ;; proper mask, just too small
+ )
+ )
+ )
+ (func $local-info-zero-ext (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.const 212) ;; mask is unneeded, we are small
+ )
+ (drop
+ (i32.and
+ (get_local $x)
+ (i32.const 255)
+ )
+ )
+ (set_local $y
+ (i32.const 500) ;; mask is needed, we are too big
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (set_local $0
+ (i32.const 212) ;; mask is unneeded, but we are a param, not a var, so no
+ )
+ (drop
+ (i32.and
+ (get_local $0)
+ (i32.const 255)
+ )
+ )
+ (set_local $z
+ (i32.const 212) ;; mask is unneeded, we are small
+ )
+ (set_local $z
+ (i32.const 220) ;; mask is still unneeded even with 2 uses
+ )
+ (drop
+ (i32.and
+ (get_local $z)
+ (i32.const 255)
+ )
+ )
+ (set_local $w
+ (i32.const 212) ;; mask is unneeded, we are small
+ )
+ (set_local $w
+ (i32.const 1000) ;; mask is needed, one use is too big
+ )
+ (drop
+ (i32.and
+ (get_local $w)
+ (i32.const 255)
+ )
+ )
+ )
+ (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.const 127) ;; mask is unneeded, we are small
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $x)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $y
+ (i32.const 128) ;; mask is needed, we are too big
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $0
+ (i32.const 127) ;; mask is unneeded, but we are a param, not a var, so no
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.const 127) ;; mask is unneeded, we are small
+ )
+ (set_local $z
+ (i32.const 100) ;; mask is still unneeded even with 2 uses
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $z)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $w
+ (i32.const 127) ;; mask is unneeded, we are small
+ )
+ (set_local $w
+ (i32.const 150) ;; mask is needed, one use is too big
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $w)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.shr_s
+ (i32.shl
+ (get_local $0) ;; already sign-exted here, so no need later
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $x)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $y
+ (i32.shr_s
+ (i32.shl
+ (get_local $0) ;; already sign-exted here, but wrong bit size
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $0
+ (i32.shr_s
+ (i32.shl
+ (get_local $0) ;; already sign-exted here, so no need later, but we are a param
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $0)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.shr_s
+ (i32.shl
+ (get_local $0) ;; already sign-exted here, so no need later
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.shr_s
+ (i32.shl
+ (get_local $1) ;; already sign-exted here, so no need later
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $z)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $w
+ (i32.shr_s
+ (i32.shl
+ (get_local $0) ;; already sign-exted here, so no need later
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $w
+ (i32.shr_s
+ (i32.shl
+ (get_local $0) ;; not quite a sign-ext
+ (i32.const 23)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $w)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (drop ;; odd corner case
+ (i32.shr_s
+ (i32.shl
+ (get_local $0) ;; param, so we should know nothing
+ (i32.const 24)
+ )
+ (i32.const 23) ;; different shift, smaller
+ )
+ )
+ )
+ (func $signed-loads-fill-the-bits (param $$e i32) (result i32)
+ (local $$0 i32)
+ (local $$conv i32)
+ (set_local $$0
+ (i32.load8_s ;; one byte, but 32 bits due to sign-extend
+ (i32.const 1024)
+ )
+ )
+ (set_local $$conv
+ (i32.and
+ (get_local $$0)
+ (i32.const 255) ;; so we need this zexting!
+ )
+ )
+ (return
+ (i32.eq
+ (get_local $$conv)
+ (get_local $$e)
+ )
+ )
+ )
+ (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32)
+ (local $x i32)
+ (local $y i32)
+ (local $z i32)
+ (local $w i32)
+ (set_local $x
+ (i32.load8_s (i32.const 1024)) ;; 8 bits, sign extended, no need to do it again
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $x)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $y
+ (i32.load8_u (i32.const 1024)) ;; 8 bits, zext, so bad
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ (set_local $z
+ (i32.load16_s (i32.const 1024)) ;; 16 bits sign-extended, wrong size
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $z)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32)
+ (drop
+ (i32.eq
+ (i32.load8_s
+ (get_local $0)
+ )
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.load8_s
+ (get_local $0) ;; flip order, we should canonicalize
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.load8_u ;; unsigned, bad
+ (get_local $0)
+ )
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.load8_s
+ (get_local $0)
+ )
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 16) ;; wrong size
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ (i32.load8_u ;; unsigned, bad
+ (get_local $0)
+ )
+ )
+ )
+ (drop
+ (i32.eq
+ (i32.shr_s
+ (i32.shl
+ (get_local $1)
+ (i32.const 16) ;; wrong size
+ )
+ (i32.const 16)
+ )
+ (i32.load8_s
+ (get_local $0)
+ )
+ )
+ )
+ )
)
diff --git a/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt b/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt
index 243421e8c..6e2127495 100644
--- a/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt
+++ b/test/passes/optimize-instructions_optimize-level=2_ignore-implicit-traps.txt
@@ -115,10 +115,7 @@
(i32.add
(i32.mul
(tee_local $7
- (i32.add
- (get_local $0)
- (i32.const 0)
- )
+ (get_local $0)
)
(get_local $0)
)
@@ -211,10 +208,7 @@
(i32.add
(i32.mul
(i32.eqz
- (i32.add
- (get_local $0)
- (i32.const 0)
- )
+ (get_local $0)
)
(get_local $0)
)
diff --git a/test/passes/pick-load-signs.txt b/test/passes/pick-load-signs.txt
new file mode 100644
index 000000000..bbf6dc647
--- /dev/null
+++ b/test/passes/pick-load-signs.txt
@@ -0,0 +1,263 @@
+(module
+ (type $0 (func))
+ (type $1 (func (result i32)))
+ (memory $0 0)
+ (func $a (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ )
+ (func $b (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load16_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 65535)
+ )
+ )
+ )
+ (func $c (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ )
+ (func $d (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load16_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 65535)
+ )
+ )
+ )
+ (func $one-of-each (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $more-of-one (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $many-more-of-one (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $a-sign (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $multivar (type $0)
+ (local $x i32)
+ (local $y i32)
+ (set_local $x
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $x)
+ (i32.const 255)
+ )
+ )
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $corners (type $0)
+ (local $y i32)
+ (drop
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (set_local $y
+ (i32.const 1024)
+ )
+ )
+ (func $wrong-size (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 65535)
+ )
+ )
+ )
+ (func $wrong-size_s (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (func $non-sign-or-unsigned-use (type $0)
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (get_local $y)
+ )
+ )
+ (func $toplevel-load (type $1) (result i32)
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+)
diff --git a/test/passes/pick-load-signs.wast b/test/passes/pick-load-signs.wast
new file mode 100644
index 000000000..49105e497
--- /dev/null
+++ b/test/passes/pick-load-signs.wast
@@ -0,0 +1,260 @@
+(module
+ (func $a ;; load 8s, but use is 8u, so load should be signed
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ )
+ (func $b ;; load 16s, but use is 16u, so load should be signed
+ (local $y i32)
+ (set_local $y
+ (i32.load16_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 65535)
+ )
+ )
+ )
+ (func $c ;; load 8u, keep
+ (local $y i32)
+ (set_local $y
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ )
+ (func $d ;; load 16u, keep
+ (local $y i32)
+ (set_local $y
+ (i32.load16_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 65535)
+ )
+ )
+ )
+ (func $one-of-each ;; prefer the signed, potential code removal is bigger
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $more-of-one ;; prefer the signed even if 2x more unsigned
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $many-more-of-one ;; but not 3x
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $a-sign ;; load 8s, use is s, so keep
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $multivar
+ (local $x i32)
+ (local $y i32)
+ (set_local $x
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $x)
+ (i32.const 255)
+ )
+ )
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 24)
+ )
+ (i32.const 24)
+ )
+ )
+ )
+ (func $corners
+ (local $y i32)
+ (drop
+ (i32.load8_s ;; not sent into a set_local
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.load8_u ;; not sent into a set_local
+ (i32.const 1024)
+ )
+ )
+ (set_local $y
+ (i32.const 1024) ;; not a load
+ )
+ )
+ (func $wrong-size ;; load 8s, but use is 16
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 65535)
+ )
+ )
+ )
+ (func $wrong-size_s ;; load 8s, but use is 16
+ (local $y i32)
+ (set_local $y
+ (i32.load8_u
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.shr_s
+ (i32.shl
+ (get_local $y)
+ (i32.const 16)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ (func $non-sign-or-unsigned-use
+ (local $y i32)
+ (set_local $y
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+ (drop
+ (i32.and
+ (get_local $y)
+ (i32.const 255)
+ )
+ )
+ (drop
+ (get_local $y)
+ )
+ )
+ (func $toplevel-load (result i32)
+ (i32.load8_s
+ (i32.const 1024)
+ )
+ )
+)