Index: src/arm/lithium-arm.cc |
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc |
index 548da2e40904f936f6b1940d390a2fd188e70287..d9f9053afb622d60c9198db0f48c138f167ea0c9 100644 |
--- a/src/arm/lithium-arm.cc |
+++ b/src/arm/lithium-arm.cc |
@@ -1446,43 +1446,61 @@ LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
+ HValue* left = instr->left(); |
+ HValue* right = instr->right(); |
if (instr->representation().IsInteger32()) { |
- ASSERT(instr->left()->representation().IsInteger32()); |
- ASSERT(instr->right()->representation().IsInteger32()); |
- |
- LModI* mod; |
+ ASSERT(left->representation().IsInteger32()); |
+ ASSERT(right->representation().IsInteger32()); |
if (instr->HasPowerOf2Divisor()) { |
- ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
- LOperand* value = UseRegisterAtStart(instr->left()); |
- mod = new(zone()) LModI(value, UseOrConstant(instr->right())); |
- } else { |
- LOperand* dividend = UseRegister(instr->left()); |
- LOperand* divisor = UseRegister(instr->right()); |
- mod = new(zone()) LModI(dividend, |
- divisor, |
- TempRegister(), |
- FixedTemp(d10), |
- FixedTemp(d11)); |
- } |
- |
- if (instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
- instr->CheckFlag(HValue::kCanBeDivByZero) || |
- instr->CheckFlag(HValue::kCanOverflow)) { |
+ ASSERT(!right->CanBeZero()); |
+ LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
+ UseOrConstant(right)); |
+ LInstruction* result = DefineAsRegister(mod); |
+ return (left->CanBeNegative() && |
+ instr->CheckFlag(HValue::kBailoutOnMinusZero)) |
+ ? AssignEnvironment(result) |
+ : result; |
+ } else if (instr->has_fixed_right_arg()) { |
+ LModI* mod = new(zone()) LModI(UseRegisterAtStart(left), |
+ UseRegisterAtStart(right)); |
return AssignEnvironment(DefineAsRegister(mod)); |
+ } else if (CpuFeatures::IsSupported(SUDIV)) { |
+ LModI* mod = new(zone()) LModI(UseRegister(left), |
+ UseRegister(right)); |
+ LInstruction* result = DefineAsRegister(mod); |
+ return (right->CanBeZero() || |
+ (left->RangeCanInclude(kMinInt) && |
+ right->RangeCanInclude(-1) && |
+ instr->CheckFlag(HValue::kBailoutOnMinusZero)) || |
+ (left->CanBeNegative() && |
+ instr->CanBeZero() && |
+ instr->CheckFlag(HValue::kBailoutOnMinusZero))) |
+ ? AssignEnvironment(result) |
+ : result; |
} else { |
- return DefineAsRegister(mod); |
+ LModI* mod = new(zone()) LModI(UseRegister(left), |
+ UseRegister(right), |
+ FixedTemp(d10), |
+ FixedTemp(d11)); |
+ LInstruction* result = DefineAsRegister(mod); |
+ return (right->CanBeZero() || |
+ (left->CanBeNegative() && |
+ instr->CanBeZero() && |
+ instr->CheckFlag(HValue::kBailoutOnMinusZero))) |
+ ? AssignEnvironment(result) |
+ : result; |
} |
} else if (instr->representation().IsSmiOrTagged()) { |
return DoArithmeticT(Token::MOD, instr); |
} else { |
ASSERT(instr->representation().IsDouble()); |
- // We call a C function for double modulo. It can't trigger a GC. |
- // We need to use fixed result register for the call. |
+ // We call a C function for double modulo. It can't trigger a GC. We need |
+ // to use fixed result register for the call. |
// TODO(fschneider): Allow any register as input registers. |
- LOperand* left = UseFixedDouble(instr->left(), d1); |
- LOperand* right = UseFixedDouble(instr->right(), d2); |
- LArithmeticD* result = new(zone()) LArithmeticD(Token::MOD, left, right); |
- return MarkAsCall(DefineFixedDouble(result, d1), instr); |
+ LArithmeticD* mod = new(zone()) LArithmeticD(Token::MOD, |
+ UseFixedDouble(left, d1), |
+ UseFixedDouble(right, d2)); |
+ return MarkAsCall(DefineFixedDouble(mod, d1), instr); |
} |
} |