summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2022-09-06 23:56:06 +0300
committerGitHub <noreply@github.com>2022-09-06 13:56:06 -0700
commitbd5422c8f13265cf89bdf49f30a04b882ee91d0e (patch)
tree86f6158549557dfed7da1f5c48a34dc8a6eeff5d /src/passes/OptimizeInstructions.cpp
parente584f69e12b261740da6da87f0cc4550f2312bdb (diff)
downloadbinaryen-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.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)