| Index: src/x64/lithium-codegen-x64.cc
|
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
|
| index cca99a12b22facbcbfc0b2c6f836b2d7baa14ac8..8fd3d5a61727eb7e155eed9eb9a4c5c0b1d2edc2 100644
|
| --- a/src/x64/lithium-codegen-x64.cc
|
| +++ b/src/x64/lithium-codegen-x64.cc
|
| @@ -752,41 +752,65 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
|
|
|
|
|
| void LCodeGen::DoModI(LModI* instr) {
|
| - LOperand* right = instr->InputAt(1);
|
| - ASSERT(ToRegister(instr->result()).is(rdx));
|
| - ASSERT(ToRegister(instr->InputAt(0)).is(rax));
|
| - ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
|
| - ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
|
| + if (HMod::cast(instr->hydrogen())->HasPowerOf2Divisor()) {
|
| + Register dividend = ToRegister(instr->InputAt(0));
|
|
|
| - Register right_reg = ToRegister(right);
|
| + int32_t divisor =
|
| + HConstant::cast(
|
| + HMod::cast(instr->hydrogen())->right())->Integer32Value();
|
|
|
| - // Check for x % 0.
|
| - if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| - __ testl(right_reg, right_reg);
|
| - DeoptimizeIf(zero, instr->environment());
|
| - }
|
| + if (divisor < 0) divisor = -divisor;
|
|
|
| - // Sign extend eax to edx. (We are using only the low 32 bits of the values.)
|
| - __ cdq();
|
| + NearLabel positive_dividend, done;
|
| + __ testl(dividend, dividend);
|
| + __ j(not_sign, &positive_dividend);
|
| + __ negl(dividend);
|
| + __ andl(dividend, Immediate(divisor - 1));
|
| + __ negl(dividend);
|
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + __ j(not_zero, &done);
|
| + DeoptimizeIf(no_condition, instr->environment());
|
| + }
|
| + __ bind(&positive_dividend);
|
| + __ andl(dividend, Immediate(divisor - 1));
|
| + __ bind(&done);
|
| + } else {
|
| + LOperand* right = instr->InputAt(1);
|
| + Register right_reg = ToRegister(right);
|
|
|
| - // Check for (0 % -x) that will produce negative zero.
|
| - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| - NearLabel positive_left;
|
| - NearLabel done;
|
| - __ testl(rax, rax);
|
| - __ j(not_sign, &positive_left);
|
| - __ idivl(right_reg);
|
| + ASSERT(ToRegister(instr->result()).is(rdx));
|
| + ASSERT(ToRegister(instr->InputAt(0)).is(rax));
|
| + ASSERT(!right_reg.is(rax));
|
| + ASSERT(!right_reg.is(rdx));
|
|
|
| - // Test the remainder for 0, because then the result would be -0.
|
| - __ testl(rdx, rdx);
|
| - __ j(not_zero, &done);
|
| + // Check for x % 0.
|
| + if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
| + __ testl(right_reg, right_reg);
|
| + DeoptimizeIf(zero, instr->environment());
|
| + }
|
|
|
| - DeoptimizeIf(no_condition, instr->environment());
|
| - __ bind(&positive_left);
|
| - __ idivl(right_reg);
|
| - __ bind(&done);
|
| - } else {
|
| - __ idivl(right_reg);
|
| + // Sign extend eax to edx. (We are using only the low 32 bits of the values.)
|
| + __ cdq();
|
| +
|
| + // Check for (0 % -x) that will produce negative zero.
|
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
| + NearLabel positive_left;
|
| + NearLabel done;
|
| + __ testl(rax, rax);
|
| + __ j(not_sign, &positive_left);
|
| + __ idivl(right_reg);
|
| +
|
| + // Test the remainder for 0, because then the result would be -0.
|
| + __ testl(rdx, rdx);
|
| + __ j(not_zero, &done);
|
| +
|
| + DeoptimizeIf(no_condition, instr->environment());
|
| + __ bind(&positive_left);
|
| + __ idivl(right_reg);
|
| + __ bind(&done);
|
| + } else {
|
| + __ idivl(right_reg);
|
| + }
|
| }
|
| }
|
|
|
|
|