diff options
author | Max Graey <maxgraey@gmail.com> | 2020-10-07 21:13:06 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-07 11:13:06 -0700 |
commit | 6fbf158b04f6ba2771f4856e41d070086b5b0d96 (patch) | |
tree | 9243b8092d102b692d4e424545026e32c238592a /src/passes/OptimizeInstructions.cpp | |
parent | fe56186c48350e7b4b4a2243022da65703a8f1b7 (diff) | |
download | binaryen-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.cpp | 35 |
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>()) { |