summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2020-11-05 02:05:10 +0200
committerGitHub <noreply@github.com>2020-11-04 16:05:10 -0800
commit3cae759a6ddf2b69a343270f612cdd92dc00f892 (patch)
tree4ea43ecec8f72e751eaeabc81abfa467b230bb92 /src
parente85122d218aed06e81ecf0279a0da8199a85131b (diff)
downloadbinaryen-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.cpp96
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;