diff options
author | Max Graey <maxgraey@gmail.com> | 2020-11-05 02:05:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-04 16:05:10 -0800 |
commit | 3cae759a6ddf2b69a343270f612cdd92dc00f892 (patch) | |
tree | 4ea43ecec8f72e751eaeabc81abfa467b230bb92 /src | |
parent | e85122d218aed06e81ecf0279a0da8199a85131b (diff) | |
download | binaryen-3cae759a6ddf2b69a343270f612cdd92dc00f892.tar.gz binaryen-3cae759a6ddf2b69a343270f612cdd92dc00f892.tar.bz2 binaryen-3cae759a6ddf2b69a343270f612cdd92dc00f892.zip |
Optimize signed / unsigned relationals when RHS is min or max constant (#3314)
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 96 |
1 files changed, 89 insertions, 7 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index ecd30d711..24b7ee845 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1592,12 +1592,30 @@ private: curr->type = Type::i32; return Builder(*getModule()).makeUnary(ExtendUInt32, curr); } - // (unsigned)x > -1 ==> 0 + // (unsigned)x < 0 ==> i32(0) + if (matches(curr, binary(LtU, pure(&left), ival(0)))) { + right->value = Literal::makeZero(Type::i32); + right->type = Type::i32; + return right; + } + // (unsigned)x <= -1 ==> i32(1) + if (matches(curr, binary(LeU, pure(&left), ival(-1)))) { + right->value = Literal::makeOne(Type::i32); + right->type = Type::i32; + return right; + } + // (unsigned)x > -1 ==> i32(0) if (matches(curr, binary(GtU, pure(&left), ival(-1)))) { right->value = Literal::makeZero(Type::i32); right->type = Type::i32; return right; } + // (unsigned)x >= 0 ==> i32(1) + if (matches(curr, binary(GeU, pure(&left), ival(0)))) { + right->value = Literal::makeOne(Type::i32); + right->type = Type::i32; + return right; + } // (unsigned)x < -1 ==> x != -1 // Friendlier to JS emitting as we don't need to write an unsigned -1 value // which is large. @@ -1605,6 +1623,76 @@ private: curr->op = Abstract::getBinary(type, Ne); return curr; } + // (unsigned)x <= 0 ==> x == 0 + if (matches(curr, binary(LeU, any(), ival(0)))) { + curr->op = Abstract::getBinary(type, Eq); + return curr; + } + // (unsigned)x > 0 ==> x != 0 + if (matches(curr, binary(GtU, any(), ival(0)))) { + curr->op = Abstract::getBinary(type, Ne); + return curr; + } + // (unsigned)x >= -1 ==> x == -1 + if (matches(curr, binary(GeU, any(), ival(-1)))) { + curr->op = Abstract::getBinary(type, Eq); + return curr; + } + { + Const* c; + // (signed)x < (i32|i64).min_s ==> i32(0) + if (matches(curr, binary(LtS, pure(&left), ival(&c))) && + c->value.isSignedMin()) { + right->value = Literal::makeZero(Type::i32); + right->type = Type::i32; + return right; + } + // (signed)x <= (i32|i64).max_s ==> i32(1) + if (matches(curr, binary(LeS, pure(&left), ival(&c))) && + c->value.isSignedMax()) { + right->value = Literal::makeOne(Type::i32); + right->type = Type::i32; + return right; + } + // (signed)x > (i32|i64).max_s ==> i32(0) + if (matches(curr, binary(GtS, pure(&left), ival(&c))) && + c->value.isSignedMax()) { + right->value = Literal::makeZero(Type::i32); + right->type = Type::i32; + return right; + } + // (signed)x >= (i32|i64).min_s ==> i32(1) + if (matches(curr, binary(GeS, pure(&left), ival(&c))) && + c->value.isSignedMin()) { + right->value = Literal::makeOne(Type::i32); + right->type = Type::i32; + return right; + } + // (signed)x < (i32|i64).max_s ==> x != (i32|i64).max_s + if (matches(curr, binary(LtS, any(), ival(&c))) && + c->value.isSignedMax()) { + curr->op = Abstract::getBinary(type, Ne); + return curr; + } + // (signed)x <= (i32|i64).min_s ==> x == (i32|i64).min_s + if (matches(curr, binary(LeS, any(), ival(&c))) && + c->value.isSignedMin()) { + curr->op = Abstract::getBinary(type, Eq); + return curr; + } + // (signed)x > (i32|i64).min_s ==> x != (i32|i64).min_s + if (matches(curr, binary(GtS, any(), ival(&c))) && + c->value.isSignedMin()) { + curr->op = Abstract::getBinary(type, Ne); + return curr; + } + // (signed)x >= (i32|i64).max_s ==> x == (i32|i64).max_s + if (matches(curr, binary(GeS, any(), ival(&c))) && + c->value.isSignedMax()) { + curr->op = Abstract::getBinary(type, Eq); + return curr; + } + } // x * -1 ==> 0 - x if (matches(curr, binary(Mul, any(&left), ival(-1)))) { right->value = Literal::makeZero(type); @@ -1613,12 +1701,6 @@ private: curr->right = left; return curr; } - // (unsigned)x <= -1 ==> 1 - if (matches(curr, binary(LeU, pure(&left), ival(-1)))) { - right->value = Literal::makeOne(Type::i32); - right->type = Type::i32; - return right; - } { // ~(1 << x) aka (1 << x) ^ -1 ==> rotl(-2, x) Expression* x; |