Index: src/mips/lithium-mips.cc |
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc |
index d4f450e5c4ce60be2cdaaeb3a6e961223055ac57..5835e68eb5d73674c121ea5ae3e6192a9f2f2257 100644 |
--- a/src/mips/lithium-mips.cc |
+++ b/src/mips/lithium-mips.cc |
@@ -1369,12 +1369,59 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
} |
-LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
- UNIMPLEMENTED(); |
+bool LChunkBuilder::HasMagicNumberForDivisor(int32_t divisor) { |
+ uint32_t divisor_abs = abs(divisor); |
+ // Dividing by 0, 1, and powers of 2 is easy. |
+ // Note that IsPowerOf2(0) returns true; |
+ ASSERT(IsPowerOf2(0) == true); |
+ if (IsPowerOf2(divisor_abs)) return true; |
+ |
+ // We have 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> |
+ int32_t power_of_2_factor = |
+ CompilerIntrinsics::CountTrailingZeros(divisor_abs); |
+ DivMagicNumbers magic_numbers = |
+ DivMagicNumberFor(divisor_abs >> power_of_2_factor); |
+ if (magic_numbers.M != InvalidDivMagicNumber.M) return true; |
+ |
+ return false; |
+} |
+ |
+ |
+HValue* LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(HValue* divisor) { |
+ // Only optimize when we have magic numbers for the divisor. |
+ // The standard integer division routine is usually slower than transitionning |
+ // to FPU. |
+ if (divisor->IsConstant() && |
+ HConstant::cast(divisor)->HasInteger32Value()) { |
+ HConstant* constant_val = HConstant::cast(divisor); |
+ return constant_val->CopyToRepresentation(Representation::Integer32(), |
+ divisor->block()->zone()); |
+ } |
return NULL; |
} |
+LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
+ HValue* right = instr->right(); |
+ LOperand* dividend = UseRegister(instr->left()); |
+ LOperand* divisor = UseRegisterOrConstant(right); |
+ LOperand* remainder = TempRegister(); |
+ ASSERT(right->IsConstant() && |
+ HConstant::cast(right)->HasInteger32Value()); |
+ return AssignEnvironment(DefineAsRegister( |
+ new(zone()) LMathFloorOfDiv(dividend, divisor, remainder))); |
+} |
+ |
+ |
LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
HValue* left = instr->left(); |
HValue* right = instr->right(); |