summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 047ed8551..672484c92 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -3564,6 +3564,55 @@ private:
}
}
{
+ // TODO: Add cancelation for some large constants when shrinkLevel > 0
+ // in FinalOptimizer.
+
+ // (x >> C) << C => x & -(1 << C)
+ // (x >>> C) << C => x & -(1 << C)
+ Binary* inner;
+ Const *c1, *c2;
+ if (matches(curr,
+ binary(Shl, binary(&inner, any(), ival(&c1)), ival(&c2))) &&
+ (inner->op == getBinary(inner->type, ShrS) ||
+ inner->op == getBinary(inner->type, ShrU)) &&
+ Bits::getEffectiveShifts(c1) == Bits::getEffectiveShifts(c2)) {
+ auto type = c1->type;
+ if (type == Type::i32) {
+ c1->value = Literal::makeFromInt32(
+ -(1U << Bits::getEffectiveShifts(c1)), Type::i32);
+ } else {
+ c1->value = Literal::makeFromInt64(
+ -(1ULL << Bits::getEffectiveShifts(c1)), Type::i64);
+ }
+ inner->op = getBinary(type, And);
+ return inner;
+ }
+ }
+ {
+ // TODO: Add cancelation for some large constants when shrinkLevel > 0
+ // in FinalOptimizer.
+
+ // (x << C) >>> C => x & (-1 >>> C)
+ // (x << C) >> C => skip
+ Binary* inner;
+ Const *c1, *c2;
+ if (matches(
+ curr,
+ binary(ShrU, binary(&inner, Shl, any(), ival(&c1)), ival(&c2))) &&
+ Bits::getEffectiveShifts(c1) == Bits::getEffectiveShifts(c2)) {
+ auto type = c1->type;
+ if (type == Type::i32) {
+ c1->value = Literal::makeFromInt32(
+ -1U >> Bits::getEffectiveShifts(c1), Type::i32);
+ } else {
+ c1->value = Literal::makeFromInt64(
+ -1ULL >> Bits::getEffectiveShifts(c1), Type::i64);
+ }
+ inner->op = getBinary(type, And);
+ return inner;
+ }
+ }
+ {
// TODO: Add canonicalization rotr to rotl and remove these rules.
// rotl(rotr(x, C1), C2) => rotr(x, C1 - C2)
// rotr(rotl(x, C1), C2) => rotl(x, C1 - C2)