Index: src/a64/lithium-codegen-a64.cc |
diff --git a/src/a64/lithium-codegen-a64.cc b/src/a64/lithium-codegen-a64.cc |
index 1f8deea7f3afd089e764be108bcc349c814f1b1e..2dab3df4d9842d829e9350ba1b243fad20c312d6 100644 |
--- a/src/a64/lithium-codegen-a64.cc |
+++ b/src/a64/lithium-codegen-a64.cc |
@@ -2582,131 +2582,104 @@ void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
void LCodeGen::DoDivI(LDivI* instr) { |
- Register dividend = ToRegister32(instr->left()); |
- Register result = ToRegister32(instr->result()); |
- |
- bool has_power_of_2_divisor = instr->hydrogen()->RightIsPowerOf2(); |
- bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
- bool bailout_on_minus_zero = |
- instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
- bool can_be_div_by_zero = |
- instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero); |
- bool all_uses_truncating_to_int32 = |
- instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32); |
+ if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { |
+ HDiv* hdiv = instr->hydrogen(); |
+ Register dividend = ToRegister32(instr->left()); |
+ int32_t divisor = hdiv->right()->GetInteger32Constant(); |
+ Register result = ToRegister32(instr->result()); |
+ ASSERT(!result.is(dividend)); |
- if (has_power_of_2_divisor) { |
- ASSERT(instr->temp() == NULL); |
- int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
- int32_t power; |
- int32_t power_mask; |
- Label deopt, done; |
- |
- ASSERT(divisor != 0); |
- if (divisor > 0) { |
- power = WhichPowerOf2(divisor); |
- power_mask = divisor - 1; |
- } else { |
- // Check for (0 / -x) as that will produce negative zero. |
- if (bailout_on_minus_zero) { |
- if (all_uses_truncating_to_int32) { |
- // If all uses truncate, and the dividend is zero, the truncated |
- // result is zero. |
- __ Mov(result, 0); |
- __ Cbz(dividend, &done); |
- } else { |
- __ Cbz(dividend, &deopt); |
- } |
- } |
- // Check for (kMinInt / -1). |
- if ((divisor == -1) && can_overflow && !all_uses_truncating_to_int32) { |
- // Check for kMinInt by subtracting one and checking for overflow. |
- __ Cmp(dividend, 1); |
- __ B(vs, &deopt); |
- } |
- power = WhichPowerOf2(-divisor); |
- power_mask = -divisor - 1; |
+ // Check for (0 / -x) that will produce negative zero. |
+ if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && |
+ hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
+ __ Cmp(dividend, 0); |
+ DeoptimizeIf(eq, instr->environment()); |
} |
- |
- if (power_mask != 0) { |
- if (all_uses_truncating_to_int32) { |
- __ Cmp(dividend, 0); |
- __ Cneg(result, dividend, lt); |
- __ Asr(result, result, power); |
- if (divisor > 0) __ Cneg(result, result, lt); |
- if (divisor < 0) __ Cneg(result, result, gt); |
- return; // Don't fall through to negation below. |
- } else { |
- // Deoptimize if remainder is not 0. If the least-significant |
- // power bits aren't 0, it's not a multiple of 2^power, and |
- // therefore, there will be a remainder. |
- __ TestAndBranchIfAnySet(dividend, power_mask, &deopt); |
- __ Asr(result, dividend, power); |
- if (divisor < 0) __ Neg(result, result); |
- } |
+ // Check for (kMinInt / -1). |
+ if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 && |
+ hdiv->CheckFlag(HValue::kCanOverflow)) { |
+ __ Cmp(dividend, kMinInt); |
+ DeoptimizeIf(eq, instr->environment()); |
+ } |
+ // Deoptimize if remainder will not be 0. |
+ if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
+ Abs(divisor) != 1) { |
+ __ Tst(dividend, Abs(divisor) - 1); |
+ DeoptimizeIf(ne, instr->environment()); |
+ } |
+ if (divisor == -1) { // Nice shortcut, not needed for correctness. |
+ __ Neg(result, dividend); |
+ return; |
+ } |
+ int32_t shift = WhichPowerOf2(Abs(divisor)); |
+ if (shift == 0) { |
+ __ Mov(result, dividend); |
+ } else if (shift == 1) { |
+ __ Add(result, dividend, Operand(dividend, LSR, 31)); |
} else { |
- ASSERT((divisor == 1) || (divisor == -1)); |
- if (divisor < 0) { |
- __ Neg(result, dividend); |
- } else { |
- __ Mov(result, dividend); |
- } |
+ __ Mov(result, Operand(dividend, ASR, 31)); |
+ __ Mov(result, Operand(result, LSR, 32 - shift)); |
+ __ Add(result, result, dividend); |
Benedikt Meurer
2014/02/18 09:43:30
Please merge the last Mov and the Add.
|
} |
- __ B(&done); |
- __ Bind(&deopt); |
- Deoptimize(instr->environment()); |
- __ Bind(&done); |
- } else { |
- Register divisor = ToRegister32(instr->right()); |
- |
- // Issue the division first, and then check for any deopt cases whilst the |
- // result is computed. |
- __ Sdiv(result, dividend, divisor); |
+ if (shift > 0) __ Mov(result, Operand(result, ASR, shift)); |
+ if (divisor < 0) __ Neg(result, result); |
+ return; |
+ } |
- if (!all_uses_truncating_to_int32) { |
- Label deopt; |
- // Check for x / 0. |
- if (can_be_div_by_zero) { |
- __ Cbz(divisor, &deopt); |
- } |
+ Register dividend = ToRegister32(instr->left()); |
+ Register divisor = ToRegister32(instr->right()); |
+ Register result = ToRegister32(instr->result()); |
+ HValue* hdiv = instr->hydrogen_value(); |
- // Check for (0 / -x) as that will produce negative zero. |
- if (bailout_on_minus_zero) { |
- __ Cmp(divisor, 0); |
+ // Issue the division first, and then check for any deopt cases whilst the |
+ // result is computed. |
+ __ Sdiv(result, dividend, divisor); |
- // If the divisor < 0 (mi), compare the dividend, and deopt if it is |
- // zero, ie. zero dividend with negative divisor deopts. |
- // If the divisor >= 0 (pl, the opposite of mi) set the flags to |
- // condition ne, so we don't deopt, ie. positive divisor doesn't deopt. |
- __ Ccmp(dividend, 0, NoFlag, mi); |
- __ B(eq, &deopt); |
- } |
+ if (hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
+ ASSERT_EQ(NULL, instr->temp()); |
+ return; |
+ } |
- // Check for (kMinInt / -1). |
- if (can_overflow) { |
- // Test dividend for kMinInt by subtracting one (cmp) and checking for |
- // overflow. |
- __ Cmp(dividend, 1); |
- // If overflow is set, ie. dividend = kMinInt, compare the divisor with |
- // -1. If overflow is clear, set the flags for condition ne, as the |
- // dividend isn't -1, and thus we shouldn't deopt. |
- __ Ccmp(divisor, -1, NoFlag, vs); |
- __ B(eq, &deopt); |
- } |
+ Label deopt; |
+ // Check for x / 0. |
+ if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
+ __ Cbz(divisor, &deopt); |
+ } |
- // Compute remainder and deopt if it's not zero. |
- Register remainder = ToRegister32(instr->temp()); |
- __ Msub(remainder, result, divisor, dividend); |
- __ Cbnz(remainder, &deopt); |
+ // Check for (0 / -x) as that will produce negative zero. |
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
+ __ Cmp(divisor, 0); |
- Label div_ok; |
- __ B(&div_ok); |
- __ Bind(&deopt); |
- Deoptimize(instr->environment()); |
- __ Bind(&div_ok); |
- } else { |
- ASSERT(instr->temp() == NULL); |
- } |
+ // If the divisor < 0 (mi), compare the dividend, and deopt if it is |
+ // zero, ie. zero dividend with negative divisor deopts. |
+ // If the divisor >= 0 (pl, the opposite of mi) set the flags to |
+ // condition ne, so we don't deopt, ie. positive divisor doesn't deopt. |
+ __ Ccmp(dividend, 0, NoFlag, mi); |
+ __ B(eq, &deopt); |
} |
+ |
+ // Check for (kMinInt / -1). |
+ if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
+ // Test dividend for kMinInt by subtracting one (cmp) and checking for |
+ // overflow. |
+ __ Cmp(dividend, 1); |
+ // If overflow is set, ie. dividend = kMinInt, compare the divisor with |
+ // -1. If overflow is clear, set the flags for condition ne, as the |
+ // dividend isn't -1, and thus we shouldn't deopt. |
+ __ Ccmp(divisor, -1, NoFlag, vs); |
+ __ B(eq, &deopt); |
+ } |
+ |
+ // Compute remainder and deopt if it's not zero. |
+ Register remainder = ToRegister32(instr->temp()); |
+ __ Msub(remainder, result, divisor, dividend); |
+ __ Cbnz(remainder, &deopt); |
+ |
+ Label div_ok; |
+ __ B(&div_ok); |
+ __ Bind(&deopt); |
+ Deoptimize(instr->environment()); |
+ __ Bind(&div_ok); |
} |