summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2020-09-18 02:39:39 +0300
committerGitHub <noreply@github.com>2020-09-17 16:39:39 -0700
commit2548f04c198594a21e4144261e8cfea5de56308a (patch)
treecd3172a039e10917d34adf456093869aebddff01 /src
parent2d47c0b8ae7b72e710b982abce83429c50c6de30 (diff)
downloadbinaryen-2548f04c198594a21e4144261e8cfea5de56308a.tar.gz
binaryen-2548f04c198594a21e4144261e8cfea5de56308a.tar.bz2
binaryen-2548f04c198594a21e4144261e8cfea5de56308a.zip
Optimize binary operations with 1-bit on lhs and 1 const on rhs (#2948)
`expr | 1` --> `1` `expr & 1` --> `expr` `expr == 1` --> `expr` `expr != 1` --> `!expr` where `maxBits(expr) == 1` i.e `expr` is boolean
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp55
1 files changed, 45 insertions, 10 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index a3afa58c4..e3d2b3a57 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -235,10 +235,6 @@ struct OptimizeInstructions
}
} else if (binary->op == EqInt32 || binary->op == NeInt32) {
if (auto* c = binary->right->dynCast<Const>()) {
- if (binary->op == EqInt32 && c->value.geti32() == 0) {
- // equal 0 => eqz
- return Builder(*getModule()).makeUnary(EqZInt32, 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
@@ -812,8 +808,8 @@ private:
}
} else if (auto* binary = boolean->dynCast<Binary>()) {
if (binary->op == SubInt32) {
- if (auto* num = binary->left->dynCast<Const>()) {
- if (num->value.geti32() == 0) {
+ if (auto* c = binary->left->dynCast<Const>()) {
+ if (c->value.geti32() == 0) {
// bool(0 - x) ==> bool(x)
return binary->right;
}
@@ -824,9 +820,9 @@ private:
binary->left = optimizeBoolean(binary->left);
binary->right = optimizeBoolean(binary->right);
} else if (binary->op == NeInt32) {
- if (auto* num = binary->right->dynCast<Const>()) {
+ if (auto* c = binary->right->dynCast<Const>()) {
// x != 0 is just x if it's used as a bool
- if (num->value.geti32() == 0) {
+ if (c->value.geti32() == 0) {
return binary->left;
}
// TODO: Perhaps use it for separate final pass???
@@ -1220,8 +1216,9 @@ private:
!EffectAnalyzer(getPassOptions(), features, binary->left)
.hasSideEffects()) {
return binary->right;
- } else if (binary->op == EqInt64) {
- return Builder(*getModule()).makeUnary(EqZInt64, binary->left);
+ } else if (binary->op == Abstract::getBinary(type, Abstract::Eq)) {
+ return Builder(*getModule())
+ .makeUnary(Abstract::getUnary(type, Abstract::EqZ), binary->left);
}
}
// operations on one
@@ -1233,6 +1230,44 @@ private:
right->value = Literal::makeSingleZero(type);
return right;
}
+ // bool(x) | 1 ==> 1
+ // bool(x) & 1 ==> bool(x)
+ // bool(x) == 1 ==> bool(x)
+ // bool(x) != 1 ==> !bool(x)
+ if (Bits::getMaxBits(binary->left, this) == 1) {
+ switch (binary->op) {
+ case OrInt32:
+ case OrInt64: {
+ if (!EffectAnalyzer(getPassOptions(), features, binary->left)
+ .hasSideEffects()) {
+ // bool(x) | 1 ==> 1
+ return binary->right;
+ }
+ break;
+ }
+ case AndInt32:
+ case AndInt64:
+ case EqInt32: {
+ // bool(x) & 1 ==> bool(x)
+ // bool(x) == 1 ==> bool(x)
+ return binary->left;
+ }
+ case EqInt64: {
+ // i64(bool(x)) == 1 ==> i32(bool(x))
+ return Builder(*getModule()).makeUnary(WrapInt64, binary->left);
+ }
+ case NeInt32:
+ case NeInt64: {
+ // bool(x) != 1 ==> !bool(x)
+ return Builder(*getModule())
+ .makeUnary(
+ Abstract::getUnary(binary->left->type, Abstract::EqZ),
+ binary->left);
+ }
+ default: {
+ }
+ }
+ }
}
// operations on all 1s
if (constRight == -1LL) {