| 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: | 
|  |