Commit bf1155e8 authored by palfia@homejinni.com's avatar palfia@homejinni.com

MIPS: Consistently use a separate Lithium instruction for flooring division.

Port r20395 (5b802048)

Original commit message:
Previously we tried to share some code on by a slightly confusing re-use
of LDivI for a (general) flooring division. Now we cleanly separate
concerns, just like for the rest of the division-like operations. Note
that ARM64 already did it this way.

If we really want to save some code, we can introduce some macro
assembler instructions and/or helper functions in the code generator in
a future CL, but we should really try to avoid being "clever" to save
just a few lines of trivial code. Effort != complexity. :-)

Renamed some related Lithium operands on the way for more consistency.

BUG=
R=plind44@gmail.com

Review URL: https://codereview.chromium.org/220403009

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20417 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 97829f47
...@@ -1242,26 +1242,27 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) { ...@@ -1242,26 +1242,27 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
} }
// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
void LCodeGen::DoDivI(LDivI* instr) { void LCodeGen::DoDivI(LDivI* instr) {
HBinaryOperation* hdiv = instr->hydrogen(); HBinaryOperation* hdiv = instr->hydrogen();
const Register left = ToRegister(instr->left()); Register dividend = ToRegister(instr->dividend());
const Register right = ToRegister(instr->right()); Register divisor = ToRegister(instr->divisor());
const Register result = ToRegister(instr->result()); const Register result = ToRegister(instr->result());
// On MIPS div is asynchronous - it will run in the background while we // On MIPS div is asynchronous - it will run in the background while we
// check for special cases. // check for special cases.
__ div(left, right); __ div(dividend, divisor);
// Check for x / 0. // Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg)); DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg));
} }
// Check for (0 / -x) that will produce negative zero. // Check for (0 / -x) that will produce negative zero.
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label left_not_zero; Label left_not_zero;
__ Branch(&left_not_zero, ne, left, Operand(zero_reg)); __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg)); DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg));
__ bind(&left_not_zero); __ bind(&left_not_zero);
} }
...@@ -1269,23 +1270,12 @@ void LCodeGen::DoDivI(LDivI* instr) { ...@@ -1269,23 +1270,12 @@ void LCodeGen::DoDivI(LDivI* instr) {
if (hdiv->CheckFlag(HValue::kCanOverflow) && if (hdiv->CheckFlag(HValue::kCanOverflow) &&
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
Label left_not_min_int; Label left_not_min_int;
__ Branch(&left_not_min_int, ne, left, Operand(kMinInt)); __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr->environment(), right, Operand(-1)); DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1));
__ bind(&left_not_min_int); __ bind(&left_not_min_int);
} }
if (hdiv->IsMathFloorOfDiv()) { if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// We performed a truncating division. Correct the result if necessary.
Label done;
Register remainder = scratch0();
__ mfhi(remainder);
__ mflo(result);
__ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
__ Xor(remainder, remainder, Operand(right));
__ Branch(&done, ge, remainder, Operand(zero_reg));
__ Subu(result, result, Operand(1));
__ bind(&done);
} else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
__ mfhi(result); __ mfhi(result);
DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg)); DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
__ mflo(result); __ mflo(result);
...@@ -1398,6 +1388,52 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { ...@@ -1398,6 +1388,52 @@ void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
} }
// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
HBinaryOperation* hdiv = instr->hydrogen();
Register dividend = ToRegister(instr->dividend());
Register divisor = ToRegister(instr->divisor());
const Register result = ToRegister(instr->result());
// On MIPS div is asynchronous - it will run in the background while we
// check for special cases.
__ div(dividend, divisor);
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg));
}
// Check for (0 / -x) that will produce negative zero.
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label left_not_zero;
__ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg));
__ bind(&left_not_zero);
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) &&
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
Label left_not_min_int;
__ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1));
__ bind(&left_not_min_int);
}
// We performed a truncating division. Correct the result if necessary.
Label done;
Register remainder = scratch0();
__ mfhi(remainder);
__ mflo(result);
__ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
__ Xor(remainder, remainder, Operand(divisor));
__ Branch(&done, ge, remainder, Operand(zero_reg));
__ Subu(result, result, Operand(1));
__ bind(&done);
}
void LCodeGen::DoMulI(LMulI* instr) { void LCodeGen::DoMulI(LMulI* instr) {
Register scratch = scratch0(); Register scratch = scratch0();
Register result = ToRegister(instr->result()); Register result = ToRegister(instr->result());
......
...@@ -1295,7 +1295,7 @@ LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { ...@@ -1295,7 +1295,7 @@ LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) {
} }
LInstruction* LChunkBuilder::DoDivI(HBinaryOperation* instr) { LInstruction* LChunkBuilder::DoDivI(HDiv* instr) {
ASSERT(instr->representation().IsSmiOrInteger32()); ASSERT(instr->representation().IsSmiOrInteger32());
ASSERT(instr->left()->representation().Equals(instr->representation())); ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation())); ASSERT(instr->right()->representation().Equals(instr->representation()));
...@@ -1365,13 +1365,24 @@ LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { ...@@ -1365,13 +1365,24 @@ LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) {
} }
LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) {
ASSERT(instr->representation().IsSmiOrInteger32());
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
LOperand* divisor = UseRegister(instr->right());
LFlooringDivI* div = new(zone()) LFlooringDivI(dividend, divisor);
return AssignEnvironment(DefineAsRegister(div));
}
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
if (instr->RightIsPowerOf2()) { if (instr->RightIsPowerOf2()) {
return DoFlooringDivByPowerOf2I(instr); return DoFlooringDivByPowerOf2I(instr);
} else if (instr->right()->IsConstant()) { } else if (instr->right()->IsConstant()) {
return DoFlooringDivByConstI(instr); return DoFlooringDivByConstI(instr);
} else { } else {
return DoDivI(instr); return DoFlooringDivI(instr);
} }
} }
......
...@@ -97,6 +97,7 @@ class LCodeGen; ...@@ -97,6 +97,7 @@ class LCodeGen;
V(DummyUse) \ V(DummyUse) \
V(FlooringDivByConstI) \ V(FlooringDivByConstI) \
V(FlooringDivByPowerOf2I) \ V(FlooringDivByPowerOf2I) \
V(FlooringDivI) \
V(ForInCacheArray) \ V(ForInCacheArray) \
V(ForInPrepareMap) \ V(ForInPrepareMap) \
V(FunctionLiteral) \ V(FunctionLiteral) \
...@@ -709,13 +710,13 @@ class LDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 0> { ...@@ -709,13 +710,13 @@ class LDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 0> { class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
public: public:
LDivI(LOperand* left, LOperand* right) { LDivI(LOperand* dividend, LOperand* divisor) {
inputs_[0] = left; inputs_[0] = dividend;
inputs_[1] = right; inputs_[1] = divisor;
} }
LOperand* left() { return inputs_[0]; } LOperand* dividend() { return inputs_[0]; }
LOperand* right() { return inputs_[1]; } LOperand* divisor() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i") DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
DECLARE_HYDROGEN_ACCESSOR(BinaryOperation) DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
...@@ -761,6 +762,21 @@ class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 2> { ...@@ -761,6 +762,21 @@ class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
}; };
class LFlooringDivI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
public:
LFlooringDivI(LOperand* dividend, LOperand* divisor) {
inputs_[0] = dividend;
inputs_[1] = divisor;
}
LOperand* dividend() { return inputs_[0]; }
LOperand* divisor() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
};
class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 0> { class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
public: public:
LMulI(LOperand* left, LOperand* right) { LMulI(LOperand* left, LOperand* right) {
...@@ -2679,12 +2695,13 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { ...@@ -2679,12 +2695,13 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
LInstruction* DoMathClz32(HUnaryMathOperation* instr); LInstruction* DoMathClz32(HUnaryMathOperation* instr);
LInstruction* DoDivByPowerOf2I(HDiv* instr); LInstruction* DoDivByPowerOf2I(HDiv* instr);
LInstruction* DoDivByConstI(HDiv* instr); LInstruction* DoDivByConstI(HDiv* instr);
LInstruction* DoDivI(HBinaryOperation* instr); LInstruction* DoDivI(HDiv* instr);
LInstruction* DoModByPowerOf2I(HMod* instr); LInstruction* DoModByPowerOf2I(HMod* instr);
LInstruction* DoModByConstI(HMod* instr); LInstruction* DoModByConstI(HMod* instr);
LInstruction* DoModI(HMod* instr); LInstruction* DoModI(HMod* instr);
LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr); LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr); LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
private: private:
enum Status { enum Status {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment