summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2020-10-05 19:34:17 +0300
committerGitHub <noreply@github.com>2020-10-05 09:34:17 -0700
commit654cfca4fabda64dd91d2df9b07422b8bffc9357 (patch)
tree545adba4f335f770fc04570fe75c21a67f6a4ce4 /src/passes/OptimizeInstructions.cpp
parent3da66481b94cba2d3f5717316755fe3a60fcbe52 (diff)
downloadbinaryen-654cfca4fabda64dd91d2df9b07422b8bffc9357.tar.gz
binaryen-654cfca4fabda64dd91d2df9b07422b8bffc9357.tar.bz2
binaryen-654cfca4fabda64dd91d2df9b07422b8bffc9357.zip
Generalize transforms for #3153 (#3193)
Implement a more general (additional) version of #3153 which also handles negative constant divisors: `(int32)x % -4 == 0` --> `(x & 3) == 0` `x % -C_pot == 0` --> `(x & (abs(C_pot) - 1)) == 0` and special two-complement values as well: `(int32)x % 0x80000000 == 0` --> `(x & 0x7fffffff) == 0` `(int64)x % 0x8000000000000000 == 0` --> `(x & 0x7fffffffffffffff) == 0` as separete rules: `(int32)x % 0x80000000` --> `x & 0x7fffffff` `(int64)x % 0x8000000000000000` --> `x & 0x7fffffffffffffff` The [previous pr](https://github.com/WebAssembly/binaryen/pull/3153) didn't use these possibilities.
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp23
1 files changed, 17 insertions, 6 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 79315ac6d..de96e418e 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -298,15 +298,16 @@ struct OptimizeInstructions
}
}
{
- // eqz((signed)x % C_pot) => eqz(x & (C_pot - 1))
+ // eqz((signed)x % C_pot) => eqz(x & (abs(C_pot) - 1))
Const* c;
Binary* inner;
if (matches(curr,
unary(Abstract::EqZ,
binary(&inner, Abstract::RemS, any(), ival(&c)))) &&
- Bits::isPowerOf2((uint64_t)c->value.getInteger())) {
+ !c->value.isSignedMin() &&
+ Bits::isPowerOf2(c->value.abs().getInteger())) {
inner->op = Abstract::getBinary(c->type, Abstract::And);
- c->value = c->value.sub(Literal::makeFromInt32(1, c->type));
+ c->value = c->value.abs().sub(Literal::makeFromInt32(1, c->type));
return curr;
}
}
@@ -1307,7 +1308,16 @@ private:
right->value = Literal::makeSingleZero(type);
return right;
}
- // (signed)x % C_pot != 0 ==> x & (C_pot - 1) != 0
+ {
+ // (signed)x % (i32|i64).min_s ==> (x & (i32|i64).max_s)
+ if (matches(curr, binary(Abstract::RemS, any(&left), ival())) &&
+ right->value.isSignedMin()) {
+ curr->op = Abstract::getBinary(type, Abstract::And);
+ right->value = Literal::makeSignedMax(type);
+ return curr;
+ }
+ }
+ // (signed)x % C_pot != 0 ==> (x & (abs(C_pot) - 1)) != 0
{
Const* c;
Binary* inner;
@@ -1315,9 +1325,10 @@ private:
binary(Abstract::Ne,
binary(&inner, Abstract::RemS, any(), ival(&c)),
ival(0))) &&
- Bits::isPowerOf2((uint64_t)c->value.getInteger())) {
+ !c->value.isSignedMin() &&
+ Bits::isPowerOf2(c->value.abs().getInteger())) {
inner->op = Abstract::getBinary(c->type, Abstract::And);
- c->value = c->value.sub(Literal::makeFromInt32(1, c->type));
+ c->value = c->value.abs().sub(Literal::makeFromInt32(1, c->type));
return curr;
}
}