Chromium Code Reviews| Index: src/arm/lithium-codegen-arm.cc |
| =================================================================== |
| --- src/arm/lithium-codegen-arm.cc (revision 13014) |
| +++ src/arm/lithium-codegen-arm.cc (working copy) |
| @@ -1338,25 +1338,72 @@ |
| const Register remainder = ToRegister(instr->temp()); |
| const Register scratch = scratch0(); |
| - // We only optimize this for division by constants, because the standard |
| - // integer division routine is usually slower than transitionning to VFP. |
| - // This could be optimized on processors with SDIV available. |
| - ASSERT(instr->right()->IsConstantOperand()); |
| - int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
| - if (divisor < 0) { |
| - __ cmp(left, Operand(0)); |
| + if (instr->right()->IsConstantOperand()) { |
| + int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
| + if (LChunkBuilder::HasMagicNumberForDivisor(divisor)) { |
| + if (divisor < 0) { |
| + __ cmp(left, Operand(0)); |
| + DeoptimizeIf(eq, instr->environment()); |
| + } |
| + EmitSignedIntegerDivisionByConstant(result, |
| + left, |
| + divisor, |
| + remainder, |
| + scratch, |
| + instr->environment()); |
| + } else { |
| + // This point should never be reached if the CPU doesn't support SUDIV. |
| + ASSERT(CpuFeatures::IsSupported(SUDIV)); |
| + CpuFeatures::Scope scope(SUDIV); |
| + |
| + __ mov(scratch, ToOperand(instr->right())); |
| + __ sdiv(result, left, scratch); |
| + __ mls(remainder, result, scratch, left); |
| + } |
| + |
| + // We operated a truncating division. Correct the result if necessary. |
| + __ cmp(remainder, Operand(0)); |
| + __ teq(remainder, Operand(divisor), ne); |
| + __ sub(result, result, Operand(1), LeaveCC, mi); |
| + } else { |
| + // This point should never be reached if the CPU doesn't support SUDIV. |
| + ASSERT(CpuFeatures::IsSupported(SUDIV)); |
| + CpuFeatures::Scope scope(SUDIV); |
| + |
| + const Register right = ToRegister(instr->right()); |
| + |
| + // Check for x / 0. |
| + __ cmp(right, Operand(0)); |
| DeoptimizeIf(eq, instr->environment()); |
| + |
| + // Check for (kMinInt / -1). |
| + if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| + Label left_not_min_int; |
| + __ cmp(left, Operand(kMinInt)); |
| + __ b(ne, &left_not_min_int); |
| + __ cmp(right, Operand(-1)); |
| + DeoptimizeIf(eq, instr->environment()); |
| + __ bind(&left_not_min_int); |
| + } |
| + |
| + // Check for (0 / -x) that will produce negative zero. |
| + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| + __ cmp(right, Operand(0)); |
| + __ cmp(left, Operand(0), mi); |
| + // "right" can't be null because the code would have already been |
| + // deoptimized. The Z flag is set only if (right < 0) and (left == 0). |
| + // In this case we need to deoptimize to produce a -0. |
| + DeoptimizeIf(eq, instr->environment()); |
| + } |
| + |
| + __ sdiv(result, left, right); |
| + __ mls(remainder, result, right, left); |
| + |
| + // We operated a truncating division. Correct the result if necessary. |
|
danno
2012/11/22 11:37:59
nit: s/operated/performed
|
| + __ cmp(remainder, Operand(0)); |
| + __ teq(remainder, Operand(right), ne); |
| + __ sub(result, result, Operand(1), LeaveCC, mi); |
| } |
| - EmitSignedIntegerDivisionByConstant(result, |
| - left, |
| - divisor, |
| - remainder, |
| - scratch, |
| - instr->environment()); |
| - // We operated a truncating division. Correct the result if necessary. |
| - __ cmp(remainder, Operand(0)); |
| - __ teq(remainder, Operand(divisor), ne); |
| - __ sub(result, result, Operand(1), LeaveCC, mi); |
| } |