diff options
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>()) { |