From: plind44@gmail.com Date: Thu, 20 Mar 2014 16:04:51 +0000 (+0000) Subject: MIPS: Implement flooring division by a constant via truncating division by a constant. X-Git-Tag: upstream/4.7.83~10116 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2aadbc8f2c596fe35ba372616e2a04161e476dff;p=platform%2Fupstream%2Fv8.git MIPS: Implement flooring division by a constant via truncating division by a constant. Port r20123 (31ab416) BUG= R=plind44@gmail.com Review URL: https://codereview.chromium.org/206373004 Patch from Balazs Kilvady . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20135 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index e306c17..5e47665 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -1367,8 +1367,31 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); } - // TODO(svenpanne) Add correction terms. - __ TruncatingDiv(result, dividend, divisor); + // Easy case: We need no dynamic check for the dividend and the flooring + // division is the same as the truncating division. + if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || + (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { + __ TruncatingDiv(result, dividend, Abs(divisor)); + if (divisor < 0) __ Subu(result, zero_reg, result); + return; + } + + // In the general case we may need to adjust before and after the truncating + // division to get a flooring division. + Register temp = ToRegister(instr->temp()); + ASSERT(!temp.is(dividend) && !temp.is(result)); + Label needs_adjustment, done; + __ Branch(&needs_adjustment, divisor > 0 ? lt : gt, + dividend, Operand(zero_reg)); + __ TruncatingDiv(result, dividend, Abs(divisor)); + if (divisor < 0) __ Subu(result, zero_reg, result); + __ jmp(&done); + __ bind(&needs_adjustment); + __ Addu(temp, dividend, Operand(divisor > 0 ? 1 : -1)); + __ TruncatingDiv(result, temp, Abs(divisor)); + if (divisor < 0) __ Subu(result, zero_reg, result); + __ Subu(result, result, Operand(1)); + __ bind(&done); } diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index d2473fc..752f676 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1337,20 +1337,25 @@ LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { ASSERT(instr->right()->representation().Equals(instr->representation())); LOperand* dividend = UseRegister(instr->left()); int32_t divisor = instr->right()->GetInteger32Constant(); - LInstruction* result = - DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor)); - bool can_deopt = - divisor == 0 || - (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0); - return can_deopt ? AssignEnvironment(result) : result; + LOperand* temp = + ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) || + (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ? + NULL : TempRegister(); + LInstruction* result = DefineAsRegister( + new(zone()) LFlooringDivByConstI(dividend, divisor, temp)); + if (divisor == 0 || + (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) { + result = AssignEnvironment(result); + } + return result; } LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { if (instr->RightIsPowerOf2()) { return DoFlooringDivByPowerOf2I(instr); - } else if (false && instr->right()->IsConstant()) { - return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable. + } else if (instr->right()->IsConstant()) { + return DoFlooringDivByConstI(instr); } else { return DoDivI(instr); } diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h index 81f7fb6..ae59e57 100644 --- a/src/mips/lithium-mips.h +++ b/src/mips/lithium-mips.h @@ -741,16 +741,17 @@ class LFlooringDivByPowerOf2I V8_FINAL : public LTemplateInstruction<1, 1, 0> { }; -class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 0> { +class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 2> { public: - LFlooringDivByConstI(LOperand* dividend, int32_t divisor) { + LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) { inputs_[0] = dividend; divisor_ = divisor; + temps_[0] = temp; } LOperand* dividend() { return inputs_[0]; } int32_t divisor() const { return divisor_; } - LOperand* temp1() { return temps_[0]; } + LOperand* temp() { return temps_[0]; } DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i") DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)