Index: src/arm/lithium-codegen-arm.cc |
=================================================================== |
--- src/arm/lithium-codegen-arm.cc (revision 13038) |
+++ 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()) { |
danno
2012/11/27 22:17:20
Can you please make sure the comment about "divisi
|
+ 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); |
danno
2012/11/27 22:17:20
from here to the sub(result, result, ....) the cod
|
+ __ mls(remainder, result, scratch, left); |
+ } |
+ |
+ // We performed a truncating division. Correct the result if necessary. |
danno
2012/11/27 22:17:20
Why is it safe to omit the x/0, kMinInt/-1 and -0
|
+ __ 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 performed a truncating division. Correct the result if necessary. |
+ __ 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); |
} |