summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2020-10-07 21:13:06 +0300
committerGitHub <noreply@github.com>2020-10-07 11:13:06 -0700
commit6fbf158b04f6ba2771f4856e41d070086b5b0d96 (patch)
tree9243b8092d102b692d4e424545026e32c238592a /src/passes/OptimizeInstructions.cpp
parentfe56186c48350e7b4b4a2243022da65703a8f1b7 (diff)
downloadbinaryen-6fbf158b04f6ba2771f4856e41d070086b5b0d96.tar.gz
binaryen-6fbf158b04f6ba2771f4856e41d070086b5b0d96.tar.bz2
binaryen-6fbf158b04f6ba2771f4856e41d070086b5b0d96.zip
Add optimization rules for some shift operations (#3099)
Specifically, truncates constant shift values that are greater than the number of bits available and optimizes out explicit masking of the shift value that is redundant with the implicit masking performed by shift operations.
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index c54960079..59a38eeaa 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -350,6 +350,41 @@ struct OptimizeInstructions
return inner;
}
}
+ {
+ // x <<>> (C & (31 | 63)) ==> x <<>> C'
+ // x <<>> (y & (31 | 63)) ==> x <<>> y
+ // where '<<>>':
+ // '<<', '>>', '>>>'. 'rotl' or 'rotr'
+ BinaryOp op;
+ Const* c;
+ Expression *x, *y;
+
+ // x <<>> C
+ if (matches(curr, binary(&op, any(&x), ival(&c))) &&
+ Abstract::hasAnyShift(op)) {
+ // truncate RHS constant to effective size as:
+ // i32(x) <<>> const(C & 31))
+ // i64(x) <<>> const(C & 63))
+ c->value = c->value.and_(
+ Literal::makeFromInt32(c->type.getByteSize() * 8 - 1, c->type));
+ // x <<>> 0 ==> x
+ if (c->value.isZero()) {
+ return x;
+ }
+ }
+ if (matches(
+ curr,
+ binary(&op, any(&x), binary(Abstract::And, any(&y), ival(&c)))) &&
+ Abstract::hasAnyShift(op)) {
+ // i32(x) <<>> (y & 31) ==> x <<>> y
+ // i64(x) <<>> (y & 63) ==> x <<>> y
+ if ((c->type == Type::i32 && (c->value.geti32() & 31) == 31) ||
+ (c->type == Type::i64 && (c->value.geti64() & 63LL) == 63LL)) {
+ curr->cast<Binary>()->right = y;
+ return curr;
+ }
+ }
+ }
}
if (auto* select = curr->dynCast<Select>()) {