summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2021-10-27 02:17:33 +0300
committerGitHub <noreply@github.com>2021-10-26 23:17:33 +0000
commit2b24537425ada522d892c7180a06aedc1c94509e (patch)
treec2c08729c549a8ddb322ffb7c55c4a91c90cd9ca /src/passes/OptimizeInstructions.cpp
parent3907e07dee3ce2bd477d5c234cd7bdd6aa1294a2 (diff)
downloadbinaryen-2b24537425ada522d892c7180a06aedc1c94509e.tar.gz
binaryen-2b24537425ada522d892c7180a06aedc1c94509e.tar.bz2
binaryen-2b24537425ada522d892c7180a06aedc1c94509e.zip
[OptimizeInstructions] Canonicalize relational ops with near zero on rhs (#4272)
Canonicalize: (signed)x > -1 ==> x >= 0 (signed)x <= -1 ==> x < 0 (signed)x < 1 ==> x <= 0 (signed)x >= 1 ==> x > 0 (unsigned)x < 1 ==> x == 0 (unsigned)x >= 1 ==> x != 0 This should help #4265, and in general 0 is usually a more common constant, and reasonable to canonicalize to.
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp48
1 files changed, 46 insertions, 2 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index f23c119ec..a52126c5a 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1869,14 +1869,58 @@ private:
};
// Prefer a const on the right.
if (binary->left->is<Const>() && !binary->right->is<Const>()) {
- return swap();
+ swap();
}
if (auto* c = binary->right->dynCast<Const>()) {
- // x - C ==> x + (-C)
+ // x - C ==> x + (-C)
// Prefer use addition if there is a constant on the right.
if (binary->op == Abstract::getBinary(c->type, Abstract::Sub)) {
c->value = c->value.neg();
binary->op = Abstract::getBinary(c->type, Abstract::Add);
+ return;
+ }
+ // Prefer to compare to 0 instead of to -1 or 1.
+ // (signed)x > -1 ==> x >= 0
+ if (binary->op == Abstract::getBinary(c->type, Abstract::GtS) &&
+ c->value.getInteger() == -1LL) {
+ binary->op = Abstract::getBinary(c->type, Abstract::GeS);
+ c->value = Literal::makeZero(c->type);
+ return;
+ }
+ // (signed)x <= -1 ==> x < 0
+ if (binary->op == Abstract::getBinary(c->type, Abstract::LeS) &&
+ c->value.getInteger() == -1LL) {
+ binary->op = Abstract::getBinary(c->type, Abstract::LtS);
+ c->value = Literal::makeZero(c->type);
+ return;
+ }
+ // (signed)x < 1 ==> x <= 0
+ if (binary->op == Abstract::getBinary(c->type, Abstract::LtS) &&
+ c->value.getInteger() == 1LL) {
+ binary->op = Abstract::getBinary(c->type, Abstract::LeS);
+ c->value = Literal::makeZero(c->type);
+ return;
+ }
+ // (signed)x >= 1 ==> x > 0
+ if (binary->op == Abstract::getBinary(c->type, Abstract::GeS) &&
+ c->value.getInteger() == 1LL) {
+ binary->op = Abstract::getBinary(c->type, Abstract::GtS);
+ c->value = Literal::makeZero(c->type);
+ return;
+ }
+ // (unsigned)x < 1 ==> x == 0
+ if (binary->op == Abstract::getBinary(c->type, Abstract::LtU) &&
+ c->value.getInteger() == 1LL) {
+ binary->op = Abstract::getBinary(c->type, Abstract::Eq);
+ c->value = Literal::makeZero(c->type);
+ return;
+ }
+ // (unsigned)x >= 1 ==> x != 0
+ if (binary->op == Abstract::getBinary(c->type, Abstract::GeU) &&
+ c->value.getInteger() == 1LL) {
+ binary->op = Abstract::getBinary(c->type, Abstract::Ne);
+ c->value = Literal::makeZero(c->type);
+ return;
}
return;
}