Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion src/ir/bits.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,29 @@

namespace wasm::Bits {

// get a mask to keep only the low # of bits
// Get a mask to keep only the low # of bits.
inline int32_t lowBitMask(int32_t bits) {
uint32_t ret = -1;
if (bits <= 0) {
return 0;
}
if (bits >= 32) {
return ret;
}
return ret >> (32 - bits);
}

inline int64_t lowBitMask64(int64_t bits) {
uint64_t ret = -1;
if (bits <= 0) {
return 0;
}
if (bits >= 64) {
return ret;
}
return ret >> (64 - 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
Expand Down
39 changes: 15 additions & 24 deletions src/passes/OptimizeInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -742,25 +742,23 @@ struct OptimizeInstructions
}
// a bunch of operations on a constant right side can be simplified
if (auto* right = curr->right->dynCast<Const>()) {
if (curr->op == AndInt32) {
auto mask = right->value.geti32();
// and with -1 does nothing (common in asm.js output)
if (mask == -1) {
return replaceCurrent(curr->left);
}
// small loads do not need to be masked, the load itself masks
if (auto* load = curr->left->dynCast<Load>()) {
if ((load->bytes == 1 && mask == 0xff) ||
(load->bytes == 2 && mask == 0xffff)) {
using namespace Abstract;
using namespace Match;
Expression* left;
int64_t mask;
if (matches(curr, binary(And, any(&left), ival(&mask)))) {
// Small loads do not need to be masked, the load itself masks.
if (auto* load = left->dynCast<Load>()) {
if (mask == Bits::lowBitMask64(load->bytes * 8)) {
load->signed_ = false;
return replaceCurrent(curr->left);
}
} else if (auto maskedBits = Bits::getMaskedBits(mask)) {
if (Bits::getMaxBits(curr->left, this) <= maskedBits) {
// a mask of lower bits is not needed if we are already smaller
return replaceCurrent(curr->left);
return replaceCurrent(left);
}
}
auto lowMask = Bits::lowBitMask64(Bits::getMaxBits(left, this));
if ((mask & lowMask) == lowMask) {
// A mask of more bits than can be present is not needed.
return replaceCurrent(left);
}
}
// some math operations have trivial results
if (auto* ret = optimizeWithConstantOnRight(curr)) {
Expand Down Expand Up @@ -4525,11 +4523,8 @@ struct OptimizeInstructions
}
// i32(bool(x)) == 1 ==> i32(bool(x))
// i32(bool(x)) != 0 ==> i32(bool(x))
// i32(bool(x)) & 1 ==> i32(bool(x))
// i64(bool(x)) & 1 ==> i64(bool(x))
if ((matches(curr, binary(EqInt32, any(&left), i32(1))) ||
matches(curr, binary(NeInt32, any(&left), i32(0))) ||
matches(curr, binary(And, any(&left), ival(1)))) &&
matches(curr, binary(NeInt32, any(&left), i32(0)))) &&
Bits::getMaxBits(left, this) == 1) {
return left;
}
Expand Down Expand Up @@ -4566,10 +4561,6 @@ struct OptimizeInstructions
}

// Operations on all 1s
// x & -1 ==> x
if (matches(curr, binary(And, any(&left), ival(-1)))) {
return left;
}
// x | -1 ==> -1
if (matches(curr, binary(Or, any(&left), ival(-1)))) {
return getDroppedChildrenAndAppend(curr, right);
Expand Down
Loading
Loading