| Index: src/hydrogen.cc
|
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
|
| index 7381d022ffed8e18bb11cf933661f8bc0ea46eaa..3c50e5fcb60e02dc751de11acf54f8f0eb33b2f6 100644
|
| --- a/src/hydrogen.cc
|
| +++ b/src/hydrogen.cc
|
| @@ -8226,6 +8226,61 @@ HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context,
|
| return new(zone()) HStringCharCodeAt(context, string, checked_index);
|
| }
|
|
|
| +// Checks if the given shift amounts have form: (sa) and (32 - sa).
|
| +static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
|
| + HValue* const32_minus_sa) {
|
| + if (!const32_minus_sa->IsSub()) return false;
|
| + HSub* sub = HSub::cast(const32_minus_sa);
|
| + HValue* const32 = sub->left();
|
| + if (!const32->IsConstant() ||
|
| + HConstant::cast(const32)->Integer32Value() != 32) {
|
| + return false;
|
| + }
|
| + return (sub->right() == sa);
|
| +}
|
| +
|
| +
|
| +// Checks if the left and the right are shift instructions with the oposite
|
| +// directions that can be replaced by one rotate right instruction or not.
|
| +// Returns the operand and the shift amount for the rotate instruction in the
|
| +// former case.
|
| +bool HGraphBuilder::MatchRotateRight(HValue* left,
|
| + HValue* right,
|
| + HValue** operand,
|
| + HValue** shift_amount) {
|
| + HShl* shl;
|
| + HShr* shr;
|
| + if (left->IsShl() && right->IsShr()) {
|
| + shl = HShl::cast(left);
|
| + shr = HShr::cast(right);
|
| + } else if (left->IsShr() && right->IsShl()) {
|
| + shl = HShl::cast(right);
|
| + shr = HShr::cast(left);
|
| + } else {
|
| + return false;
|
| + }
|
| +
|
| + if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
|
| + !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
|
| + return false;
|
| + }
|
| + *operand= shr->left();
|
| + *shift_amount = shr->right();
|
| + return true;
|
| +}
|
| +
|
| +
|
| +bool CanBeZero(HValue *right) {
|
| + if (right->IsConstant()) {
|
| + HConstant* right_const = HConstant::cast(right);
|
| + if (right_const->HasInteger32Value() &&
|
| + (right_const->Integer32Value() & 0x1f) != 0) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
|
|
| HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
|
| HValue* left,
|
| @@ -8264,25 +8319,26 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
|
| break;
|
| case Token::BIT_XOR:
|
| case Token::BIT_AND:
|
| - case Token::BIT_OR:
|
| instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
|
| break;
|
| + case Token::BIT_OR: {
|
| + HValue* operand, *shift_amount;
|
| + if (info.IsInteger32() &&
|
| + MatchRotateRight(left, right, &operand, &shift_amount)) {
|
| + instr = new(zone()) HRor(context, operand, shift_amount);
|
| + } else {
|
| + instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right);
|
| + }
|
| + break;
|
| + }
|
| case Token::SAR:
|
| instr = HSar::NewHSar(zone(), context, left, right);
|
| break;
|
| case Token::SHR:
|
| instr = HShr::NewHShr(zone(), context, left, right);
|
| - if (FLAG_opt_safe_uint32_operations && instr->IsShr()) {
|
| - bool can_be_shift_by_zero = true;
|
| - if (right->IsConstant()) {
|
| - HConstant* right_const = HConstant::cast(right);
|
| - if (right_const->HasInteger32Value() &&
|
| - (right_const->Integer32Value() & 0x1f) != 0) {
|
| - can_be_shift_by_zero = false;
|
| - }
|
| - }
|
| -
|
| - if (can_be_shift_by_zero) graph()->RecordUint32Instruction(instr);
|
| + if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
|
| + CanBeZero(right)) {
|
| + graph()->RecordUint32Instruction(instr);
|
| }
|
| break;
|
| case Token::SHL:
|
|
|