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
This commit is contained in:
parent
97829f4749
commit
bf1155e8a4
@ -1242,26 +1242,27 @@ void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
|
||||
}
|
||||
|
||||
|
||||
// TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
|
||||
void LCodeGen::DoDivI(LDivI* instr) {
|
||||
HBinaryOperation* hdiv = instr->hydrogen();
|
||||
const Register left = ToRegister(instr->left());
|
||||
const Register right = ToRegister(instr->right());
|
||||
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(left, right);
|
||||
__ div(dividend, divisor);
|
||||
|
||||
// Check for x / 0.
|
||||
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.
|
||||
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
Label left_not_zero;
|
||||
__ Branch(&left_not_zero, ne, left, Operand(zero_reg));
|
||||
DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg));
|
||||
__ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
|
||||
DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg));
|
||||
__ bind(&left_not_zero);
|
||||
}
|
||||
|
||||
@ -1269,23 +1270,12 @@ void LCodeGen::DoDivI(LDivI* instr) {
|
||||
if (hdiv->CheckFlag(HValue::kCanOverflow) &&
|
||||
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
|
||||
Label left_not_min_int;
|
||||
__ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
|
||||
DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
|
||||
__ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
|
||||
DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1));
|
||||
__ bind(&left_not_min_int);
|
||||
}
|
||||
|
||||
if (hdiv->IsMathFloorOfDiv()) {
|
||||
// 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)) {
|
||||
if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
|
||||
__ mfhi(result);
|
||||
DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
|
||||
__ mflo(result);
|
||||
@ -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) {
|
||||
Register scratch = scratch0();
|
||||
Register result = ToRegister(instr->result());
|
||||
|
@ -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->left()->representation().Equals(instr->representation()));
|
||||
ASSERT(instr->right()->representation().Equals(instr->representation()));
|
||||
@ -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) {
|
||||
if (instr->RightIsPowerOf2()) {
|
||||
return DoFlooringDivByPowerOf2I(instr);
|
||||
} else if (instr->right()->IsConstant()) {
|
||||
return DoFlooringDivByConstI(instr);
|
||||
} else {
|
||||
return DoDivI(instr);
|
||||
return DoFlooringDivI(instr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +97,7 @@ class LCodeGen;
|
||||
V(DummyUse) \
|
||||
V(FlooringDivByConstI) \
|
||||
V(FlooringDivByPowerOf2I) \
|
||||
V(FlooringDivI) \
|
||||
V(ForInCacheArray) \
|
||||
V(ForInPrepareMap) \
|
||||
V(FunctionLiteral) \
|
||||
@ -709,13 +710,13 @@ class LDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
|
||||
|
||||
class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
|
||||
public:
|
||||
LDivI(LOperand* left, LOperand* right) {
|
||||
inputs_[0] = left;
|
||||
inputs_[1] = right;
|
||||
LDivI(LOperand* dividend, LOperand* divisor) {
|
||||
inputs_[0] = dividend;
|
||||
inputs_[1] = divisor;
|
||||
}
|
||||
|
||||
LOperand* left() { return inputs_[0]; }
|
||||
LOperand* right() { return inputs_[1]; }
|
||||
LOperand* dividend() { return inputs_[0]; }
|
||||
LOperand* divisor() { return inputs_[1]; }
|
||||
|
||||
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
|
||||
DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
|
||||
@ -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> {
|
||||
public:
|
||||
LMulI(LOperand* left, LOperand* right) {
|
||||
@ -2679,12 +2695,13 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
|
||||
LInstruction* DoMathClz32(HUnaryMathOperation* instr);
|
||||
LInstruction* DoDivByPowerOf2I(HDiv* instr);
|
||||
LInstruction* DoDivByConstI(HDiv* instr);
|
||||
LInstruction* DoDivI(HBinaryOperation* instr);
|
||||
LInstruction* DoDivI(HDiv* instr);
|
||||
LInstruction* DoModByPowerOf2I(HMod* instr);
|
||||
LInstruction* DoModByConstI(HMod* instr);
|
||||
LInstruction* DoModI(HMod* instr);
|
||||
LInstruction* DoFlooringDivByPowerOf2I(HMathFloorOfDiv* instr);
|
||||
LInstruction* DoFlooringDivByConstI(HMathFloorOfDiv* instr);
|
||||
LInstruction* DoFlooringDivI(HMathFloorOfDiv* instr);
|
||||
|
||||
private:
|
||||
enum Status {
|
||||
|
Loading…
Reference in New Issue
Block a user