Chromium Code Reviews| Index: src/mips/lithium-codegen-mips.cc |
| diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc |
| index 0f0257822658186cafcc7cbc201cd2f0e0376e0e..c293d9b2eb33eab4b4f5d0ddb9db1f95341a96fe 100644 |
| --- a/src/mips/lithium-codegen-mips.cc |
| +++ b/src/mips/lithium-codegen-mips.cc |
| @@ -1176,6 +1176,110 @@ void LCodeGen::DoModI(LModI* instr) { |
| } |
| +void LCodeGen::EmitSignedIntegerDivisionByConstant( |
| + Register result, |
| + Register dividend, |
| + int32_t divisor, |
| + Register remainder, |
| + Register scratch, |
| + LEnvironment* environment) { |
| + ASSERT(!AreAliased(dividend, scratch, at, no_reg)); |
| + |
|
Paul Lind
2013/06/14 16:34:58
Is there any specific reason you removed this asse
palfia
2013/06/15 00:15:25
Added ASSERT.
|
| + uint32_t divisor_abs = abs(divisor); |
| + |
| + int32_t power_of_2_factor = |
| + CompilerIntrinsics::CountTrailingZeros(divisor_abs); |
| + |
| + switch (divisor_abs) { |
| + case 0: |
| + DeoptimizeIf(al, environment); |
| + return; |
| + |
| + case 1: |
| + if (divisor > 0) { |
| + __ Move(result, dividend); |
| + } else { |
| + __ SubuAndCheckForOverflow(result, zero_reg, dividend, scratch); |
| + DeoptimizeIf(lt, environment, scratch, Operand(zero_reg)); |
| + } |
| + // Compute the remainder. |
| + __ Move(remainder, zero_reg); |
| + return; |
| + |
| + default: |
| + if (IsPowerOf2(divisor_abs)) { |
| + // Branch and condition free code for integer division by a power |
| + // of two. |
| + int32_t power = WhichPowerOf2(divisor_abs); |
| + if (power > 1) { |
| + __ sra(scratch, dividend, power - 1); |
| + } |
| + __ srl(scratch, scratch, 32 - power); |
| + __ Addu(scratch, dividend, Operand(scratch)); |
| + __ sra(result, scratch, power); |
| + // Negate if necessary. |
| + // We don't need to check for overflow because the case '-1' is |
| + // handled separately. |
| + if (divisor < 0) { |
| + ASSERT(divisor != -1); |
| + __ Subu(result, zero_reg, Operand(result)); |
| + } |
| + // Compute the remainder. |
| + if (divisor > 0) { |
| + __ sll(scratch, result, power); |
| + __ Subu(remainder, dividend, Operand(scratch)); |
| + } else { |
| + __ sll(scratch, result, power); |
| + __ Addu(remainder, dividend, Operand(scratch)); |
| + } |
| + return; |
| + } else if (LChunkBuilder::HasMagicNumberForDivisor(divisor)) { |
| + // Use magic numbers for a few specific divisors. |
| + // Details and proofs can be found in: |
| + // - Hacker's Delight, Henry S. Warren, Jr. |
| + // - The PowerPC Compiler Writer's Guide |
| + // and probably many others. |
| + // |
| + // We handle |
| + // <divisor with magic numbers> * <power of 2> |
| + // but not |
| + // <divisor with magic numbers> * <other divisor with magic numbers> |
| + DivMagicNumbers magic_numbers = |
| + DivMagicNumberFor(divisor_abs >> power_of_2_factor); |
| + // Branch and condition free code for integer division by a power |
| + // of two. |
| + const int32_t M = magic_numbers.M; |
| + const int32_t s = magic_numbers.s + power_of_2_factor; |
| + |
| + __ li(scratch, Operand(M)); |
| + __ mult(dividend, scratch); |
| + __ mfhi(scratch); |
| + if (M < 0) { |
| + __ Addu(scratch, scratch, Operand(dividend)); |
| + } |
| + if (s > 0) { |
| + __ sra(scratch, scratch, s); |
| + __ mov(scratch, scratch); |
| + } |
| + __ srl(at, dividend, 31); |
| + __ Addu(result, scratch, Operand(at)); |
| + if (divisor < 0) __ Subu(result, zero_reg, Operand(result)); |
| + // Compute the remainder. |
| + __ li(scratch, Operand(divisor)); |
| + // This sequence could be replaced with 'mls' when |
| + // it gets implemented. |
|
Paul Lind
2013/06/14 16:34:58
Remove this comment, 'mls' refers to arm instructi
palfia
2013/06/15 00:15:25
Done.
|
| + __ Mul(scratch, result, Operand(scratch)); |
| + __ Subu(remainder, dividend, Operand(scratch)); |
| + } else { |
| + __ li(scratch, Operand(divisor)); |
| + __ div(dividend, scratch); |
| + __ mfhi(remainder); |
| + __ mflo(result); |
| + } |
| + } |
| +} |
| + |
| + |
| void LCodeGen::DoDivI(LDivI* instr) { |
| const Register left = ToRegister(instr->left()); |
| const Register right = ToRegister(instr->right()); |
| @@ -1226,6 +1330,35 @@ void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
| } |
| +void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) { |
| + const Register result = ToRegister(instr->result()); |
| + const Register left = ToRegister(instr->left()); |
| + const Register remainder = ToRegister(instr->temp()); |
| + const Register scratch = scratch0(); |
| + |
| + Label done; |
| + // We only optimize this for division by constants, because the standard |
| + // integer division routine is usually slower than transitionning to FPU. |
| + ASSERT(instr->right()->IsConstantOperand()); |
| + int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); |
| + if (divisor < 0) { |
| + DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); |
| + } |
| + EmitSignedIntegerDivisionByConstant(result, |
| + left, |
| + divisor, |
| + remainder, |
| + scratch, |
| + instr->environment()); |
| + // We operated a truncating division. Correct the result if necessary. |
| + __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); |
| + __ Xor(scratch , remainder, Operand(divisor)); |
| + __ Branch(&done, ge, scratch, Operand(zero_reg)); |
| + __ Subu(result, result, Operand(1)); |
| + __ bind(&done); |
| +} |
| + |
| + |
| void LCodeGen::DoMulI(LMulI* instr) { |
| Register scratch = scratch0(); |
| Register result = ToRegister(instr->result()); |