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 <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20135 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
plind44@gmail.com 2014-03-20 16:04:51 +00:00
parent b12ff51378
commit 2aadbc8f2c
3 changed files with 42 additions and 13 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)