diff options
author | Max Graey <maxgraey@gmail.com> | 2021-10-27 02:17:33 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-26 23:17:33 +0000 |
commit | 2b24537425ada522d892c7180a06aedc1c94509e (patch) | |
tree | c2c08729c549a8ddb322ffb7c55c4a91c90cd9ca /src/passes/OptimizeInstructions.cpp | |
parent | 3907e07dee3ce2bd477d5c234cd7bdd6aa1294a2 (diff) | |
download | binaryen-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.cpp | 48 |
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; } |