diff options
author | Max Graey <maxgraey@gmail.com> | 2022-09-06 23:56:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-06 13:56:06 -0700 |
commit | bd5422c8f13265cf89bdf49f30a04b882ee91d0e (patch) | |
tree | 86f6158549557dfed7da1f5c48a34dc8a6eeff5d /src/passes/OptimizeInstructions.cpp | |
parent | e584f69e12b261740da6da87f0cc4550f2312bdb (diff) | |
download | binaryen-bd5422c8f13265cf89bdf49f30a04b882ee91d0e.tar.gz binaryen-bd5422c8f13265cf89bdf49f30a04b882ee91d0e.tar.bz2 binaryen-bd5422c8f13265cf89bdf49f30a04b882ee91d0e.zip |
[OptimizeInstructions] Simplify two binary expressions with asymmetric shifts and same constant (#4996)
(x >> C) << C -> x & -(1 << C)
(x >>> C) << C -> x & -(1 << C)
(x << C) >>> C -> x & (-1 >>> C)
// (x << C) >> C doesn't support
Found by the superoptimizer #4994
Fixes #5012
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 49 |
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) |