diff options
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 23 |
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; } } |