Revision: 20395
Author: [email protected]
Date: Tue Apr 1 11:42:42 2014 UTC
Log: Consistently use a separate Lithium instruction for flooring
division.
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.
[email protected]
Review URL: https://codereview.chromium.org/212703002
http://code.google.com/p/v8/source/detail?r=20395
Modified:
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/arm64/lithium-arm64.h
/branches/bleeding_edge/src/arm64/lithium-codegen-arm64.cc
/branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.h
/branches/bleeding_edge/src/x64/lithium-codegen-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.cc
/branches/bleeding_edge/src/x64/lithium-x64.h
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Apr 1 07:21:31 2014
UTC
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Apr 1 11:42:42 2014
UTC
@@ -1289,7 +1289,7 @@
}
-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()));
@@ -1359,6 +1359,18 @@
}
return result;
}
+
+
+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());
+ LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d4);
+ LFlooringDivI* div = new(zone()) LFlooringDivI(dividend, divisor, temp);
+ return AssignEnvironment(DefineAsRegister(div));
+}
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
@@ -1367,7 +1379,7 @@
} else if (instr->right()->IsConstant()) {
return DoFlooringDivByConstI(instr);
} else {
- return DoDivI(instr);
+ return DoFlooringDivI(instr);
}
}
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Thu Mar 20 13:10:23 2014
UTC
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Tue Apr 1 11:42:42 2014
UTC
@@ -97,6 +97,7 @@
V(DummyUse) \
V(FlooringDivByConstI) \
V(FlooringDivByPowerOf2I) \
+ V(FlooringDivI) \
V(ForInCacheArray) \
V(ForInPrepareMap) \
V(FunctionLiteral) \
@@ -713,14 +714,14 @@
class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
public:
- LDivI(LOperand* left, LOperand* right, LOperand* temp) {
- inputs_[0] = left;
- inputs_[1] = right;
+ LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
+ inputs_[0] = dividend;
+ inputs_[1] = divisor;
temps_[0] = temp;
}
- LOperand* left() { return inputs_[0]; }
- LOperand* right() { return inputs_[1]; }
+ LOperand* dividend() { return inputs_[0]; }
+ LOperand* divisor() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
@@ -767,6 +768,23 @@
};
+class LFlooringDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
+ public:
+ LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
+ inputs_[0] = dividend;
+ inputs_[1] = divisor;
+ temps_[0] = temp;
+ }
+
+ LOperand* dividend() { return inputs_[0]; }
+ LOperand* divisor() { return inputs_[1]; }
+ LOperand* temp() { return temps_[0]; }
+
+ 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) {
@@ -2722,12 +2740,13 @@
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 {
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Apr 1
09:20:28 2014 UTC
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Apr 1
11:42:42 2014 UTC
@@ -1363,15 +1363,16 @@
}
+// TODO(svenpanne) Refactor this to avoid code duplication with
DoFlooringDivI.
void LCodeGen::DoDivI(LDivI* instr) {
HBinaryOperation* hdiv = instr->hydrogen();
- Register left = ToRegister(instr->left());
- Register right = ToRegister(instr->right());
+ Register dividend = ToRegister(instr->dividend());
+ Register divisor = ToRegister(instr->divisor());
Register result = ToRegister(instr->result());
// Check for x / 0.
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
- __ cmp(right, Operand::Zero());
+ __ cmp(divisor, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
@@ -1380,10 +1381,10 @@
Label positive;
if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
// Do the test only if it hadn't be done above.
- __ cmp(right, Operand::Zero());
+ __ cmp(divisor, Operand::Zero());
}
__ b(pl, &positive);
- __ cmp(left, Operand::Zero());
+ __ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
__ bind(&positive);
}
@@ -1394,39 +1395,30 @@
!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
// We don't need to check for overflow when truncating with sdiv
// support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
- __ cmp(left, Operand(kMinInt));
- __ cmp(right, Operand(-1), eq);
+ __ cmp(dividend, Operand(kMinInt));
+ __ cmp(divisor, Operand(-1), eq);
DeoptimizeIf(eq, instr->environment());
}
if (CpuFeatures::IsSupported(SUDIV)) {
CpuFeatureScope scope(masm(), SUDIV);
- __ sdiv(result, left, right);
+ __ sdiv(result, dividend, divisor);
} else {
DoubleRegister vleft = ToDoubleRegister(instr->temp());
DoubleRegister vright = double_scratch0();
- __ vmov(double_scratch0().low(), left);
+ __ vmov(double_scratch0().low(), dividend);
__ vcvt_f64_s32(vleft, double_scratch0().low());
- __ vmov(double_scratch0().low(), right);
+ __ vmov(double_scratch0().low(), divisor);
__ vcvt_f64_s32(vright, double_scratch0().low());
__ vdiv(vleft, vleft, vright); // vleft now contains the result.
__ vcvt_s32_f64(double_scratch0().low(), vleft);
__ vmov(result, double_scratch0().low());
}
- if (hdiv->IsMathFloorOfDiv()) {
- Label done;
- Register remainder = scratch0();
- __ mls(remainder, result, right, left);
- __ cmp(remainder, Operand::Zero());
- __ b(eq, &done);
- __ eor(remainder, remainder, Operand(right));
- __ add(result, result, Operand(remainder, ASR, 31));
- __ bind(&done);
- } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
+ if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Compute remainder and deopt if it's not zero.
Register remainder = scratch0();
- __ mls(remainder, result, right, left);
+ __ mls(remainder, result, divisor, dividend);
__ cmp(remainder, Operand::Zero());
DeoptimizeIf(ne, instr->environment());
}
@@ -1536,6 +1528,69 @@
__ sub(result, result, Operand(1));
__ bind(&done);
}
+
+
+// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
+void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
+ HBinaryOperation* hdiv = instr->hydrogen();
+ Register left = ToRegister(instr->dividend());
+ Register right = ToRegister(instr->divisor());
+ Register result = ToRegister(instr->result());
+
+ // Check for x / 0.
+ if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
+ __ cmp(right, Operand::Zero());
+ DeoptimizeIf(eq, instr->environment());
+ }
+
+ // Check for (0 / -x) that will produce negative zero.
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ Label positive;
+ if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
+ // Do the test only if it hadn't be done above.
+ __ cmp(right, Operand::Zero());
+ }
+ __ b(pl, &positive);
+ __ cmp(left, Operand::Zero());
+ DeoptimizeIf(eq, instr->environment());
+ __ bind(&positive);
+ }
+
+ // Check for (kMinInt / -1).
+ if (hdiv->CheckFlag(HValue::kCanOverflow) &&
+ (!CpuFeatures::IsSupported(SUDIV) ||
+ !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
+ // We don't need to check for overflow when truncating with sdiv
+ // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
+ __ cmp(left, Operand(kMinInt));
+ __ cmp(right, Operand(-1), eq);
+ DeoptimizeIf(eq, instr->environment());
+ }
+
+ if (CpuFeatures::IsSupported(SUDIV)) {
+ CpuFeatureScope scope(masm(), SUDIV);
+ __ sdiv(result, left, right);
+ } else {
+ DoubleRegister vleft = ToDoubleRegister(instr->temp());
+ DoubleRegister vright = double_scratch0();
+ __ vmov(double_scratch0().low(), left);
+ __ vcvt_f64_s32(vleft, double_scratch0().low());
+ __ vmov(double_scratch0().low(), right);
+ __ vcvt_f64_s32(vright, double_scratch0().low());
+ __ vdiv(vleft, vleft, vright); // vleft now contains the result.
+ __ vcvt_s32_f64(double_scratch0().low(), vleft);
+ __ vmov(result, double_scratch0().low());
+ }
+
+ Label done;
+ Register remainder = scratch0();
+ __ mls(remainder, result, right, left);
+ __ cmp(remainder, Operand::Zero());
+ __ b(eq, &done);
+ __ eor(remainder, remainder, Operand(right));
+ __ add(result, result, Operand(remainder, ASR, 31));
+ __ bind(&done);
+}
void LCodeGen::DoMulI(LMulI* instr) {
=======================================
--- /branches/bleeding_edge/src/arm64/lithium-arm64.h Tue Apr 1 07:21:31
2014 UTC
+++ /branches/bleeding_edge/src/arm64/lithium-arm64.h Tue Apr 1 11:42:42
2014 UTC
@@ -1324,14 +1324,14 @@
class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
public:
- LDivI(LOperand* left, LOperand* right, LOperand* temp) {
- inputs_[0] = left;
- inputs_[1] = right;
+ LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
+ inputs_[0] = dividend;
+ inputs_[1] = divisor;
temps_[0] = temp;
}
- LOperand* left() { return inputs_[0]; }
- LOperand* right() { return inputs_[1]; }
+ LOperand* dividend() { return inputs_[0]; }
+ LOperand* divisor() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
=======================================
--- /branches/bleeding_edge/src/arm64/lithium-codegen-arm64.cc Tue Apr 1
09:20:28 2014 UTC
+++ /branches/bleeding_edge/src/arm64/lithium-codegen-arm64.cc Tue Apr 1
11:42:42 2014 UTC
@@ -2707,10 +2707,11 @@
}
+// TODO(svenpanne) Refactor this to avoid code duplication with
DoFlooringDivI.
void LCodeGen::DoDivI(LDivI* instr) {
HBinaryOperation* hdiv = instr->hydrogen();
- Register dividend = ToRegister32(instr->left());
- Register divisor = ToRegister32(instr->right());
+ Register dividend = ToRegister32(instr->dividend());
+ Register divisor = ToRegister32(instr->divisor());
Register result = ToRegister32(instr->result());
// Issue the division first, and then check for any deopt cases whilst
the
@@ -3936,6 +3937,7 @@
}
+// TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
Register dividend = ToRegister32(instr->dividend());
Register divisor = ToRegister32(instr->divisor());
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Apr 1
09:20:28 2014 UTC
+++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Apr 1
11:42:42 2014 UTC
@@ -1556,10 +1556,11 @@
}
+// TODO(svenpanne) Refactor this to avoid code duplication with
DoFlooringDivI.
void LCodeGen::DoDivI(LDivI* instr) {
HBinaryOperation* hdiv = instr->hydrogen();
- Register dividend = ToRegister(instr->left());
- Register divisor = ToRegister(instr->right());
+ Register dividend = ToRegister(instr->dividend());
+ Register divisor = ToRegister(instr->divisor());
Register remainder = ToRegister(instr->temp());
Register result = ToRegister(instr->result());
ASSERT(dividend.is(eax));
@@ -1598,15 +1599,7 @@
__ cdq();
__ idiv(divisor);
- if (hdiv->IsMathFloorOfDiv()) {
- Label done;
- __ test(remainder, remainder);
- __ j(zero, &done, Label::kNear);
- __ xor_(remainder, divisor);
- __ sar(remainder, 31);
- __ add(result, remainder);
- __ bind(&done);
- } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
+ if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deoptimize if remainder is not 0.
__ test(remainder, remainder);
DeoptimizeIf(not_zero, instr->environment());
@@ -1694,6 +1687,59 @@
__ dec(edx);
__ bind(&done);
}
+
+
+// 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());
+ Register remainder = ToRegister(instr->temp());
+ Register result = ToRegister(instr->result());
+ ASSERT(dividend.is(eax));
+ ASSERT(remainder.is(edx));
+ ASSERT(result.is(eax));
+ ASSERT(!divisor.is(eax));
+ ASSERT(!divisor.is(edx));
+
+ // Check for x / 0.
+ if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
+ __ test(divisor, divisor);
+ DeoptimizeIf(zero, instr->environment());
+ }
+
+ // Check for (0 / -x) that will produce negative zero.
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ Label dividend_not_zero;
+ __ test(dividend, dividend);
+ __ j(not_zero, ÷nd_not_zero, Label::kNear);
+ __ test(divisor, divisor);
+ DeoptimizeIf(sign, instr->environment());
+ __ bind(÷nd_not_zero);
+ }
+
+ // Check for (kMinInt / -1).
+ if (hdiv->CheckFlag(HValue::kCanOverflow)) {
+ Label dividend_not_min_int;
+ __ cmp(dividend, kMinInt);
+ __ j(not_zero, ÷nd_not_min_int, Label::kNear);
+ __ cmp(divisor, -1);
+ DeoptimizeIf(zero, instr->environment());
+ __ bind(÷nd_not_min_int);
+ }
+
+ // Sign extend to edx (= remainder).
+ __ cdq();
+ __ idiv(divisor);
+
+ Label done;
+ __ test(remainder, remainder);
+ __ j(zero, &done, Label::kNear);
+ __ xor_(remainder, divisor);
+ __ sar(remainder, 31);
+ __ add(result, remainder);
+ __ bind(&done);
+}
void LCodeGen::DoMulI(LMulI* instr) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Apr 1 07:21:31
2014 UTC
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Apr 1 11:42:42
2014 UTC
@@ -1365,7 +1365,7 @@
}
-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()));
@@ -1377,8 +1377,7 @@
if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
instr->CheckFlag(HValue::kCanOverflow) ||
- (!instr->IsMathFloorOfDiv() &&
- !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
+ !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
result = AssignEnvironment(result);
}
return result;
@@ -1440,6 +1439,24 @@
}
return result;
}
+
+
+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 = UseFixed(instr->left(), eax);
+ LOperand* divisor = UseRegister(instr->right());
+ LOperand* temp = FixedTemp(edx);
+ LInstruction* result = DefineFixed(new(zone()) LFlooringDivI(
+ dividend, divisor, temp), eax);
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+ instr->CheckFlag(HValue::kCanOverflow)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
+}
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
@@ -1448,7 +1465,7 @@
} else if (instr->right()->IsConstant()) {
return DoFlooringDivByConstI(instr);
} else {
- return DoDivI(instr);
+ return DoFlooringDivI(instr);
}
}
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Thu Mar 20 13:10:23
2014 UTC
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Tue Apr 1 11:42:42
2014 UTC
@@ -99,6 +99,7 @@
V(DummyUse) \
V(FlooringDivByConstI) \
V(FlooringDivByPowerOf2I) \
+ V(FlooringDivI) \
V(ForInCacheArray) \
V(ForInPrepareMap) \
V(FunctionLiteral) \
@@ -744,14 +745,14 @@
class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
public:
- LDivI(LOperand* left, LOperand* right, LOperand* temp) {
- inputs_[0] = left;
- inputs_[1] = right;
+ LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
+ inputs_[0] = dividend;
+ inputs_[1] = divisor;
temps_[0] = temp;
}
- LOperand* left() { return inputs_[0]; }
- LOperand* right() { return inputs_[1]; }
+ LOperand* dividend() { return inputs_[0]; }
+ LOperand* divisor() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
@@ -806,6 +807,23 @@
};
+class LFlooringDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
+ public:
+ LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
+ inputs_[0] = dividend;
+ inputs_[1] = divisor;
+ temps_[0] = temp;
+ }
+
+ LOperand* dividend() { return inputs_[0]; }
+ LOperand* divisor() { return inputs_[1]; }
+ LOperand* temp() { return temps_[0]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(FlooringDivI, "flooring-div-i")
+ DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
+};
+
+
class LMulI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
public:
LMulI(LOperand* left, LOperand* right, LOperand* temp) {
@@ -2750,12 +2768,13 @@
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 {
=======================================
--- /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Apr 1
09:20:28 2014 UTC
+++ /branches/bleeding_edge/src/x64/lithium-codegen-x64.cc Tue Apr 1
11:42:42 2014 UTC
@@ -1203,6 +1203,59 @@
__ decl(rdx);
__ bind(&done);
}
+
+
+// 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());
+ Register remainder = ToRegister(instr->temp());
+ Register result = ToRegister(instr->result());
+ ASSERT(dividend.is(rax));
+ ASSERT(remainder.is(rdx));
+ ASSERT(result.is(rax));
+ ASSERT(!divisor.is(rax));
+ ASSERT(!divisor.is(rdx));
+
+ // Check for x / 0.
+ if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
+ __ testl(divisor, divisor);
+ DeoptimizeIf(zero, instr->environment());
+ }
+
+ // Check for (0 / -x) that will produce negative zero.
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ Label dividend_not_zero;
+ __ testl(dividend, dividend);
+ __ j(not_zero, ÷nd_not_zero, Label::kNear);
+ __ testl(divisor, divisor);
+ DeoptimizeIf(sign, instr->environment());
+ __ bind(÷nd_not_zero);
+ }
+
+ // Check for (kMinInt / -1).
+ if (hdiv->CheckFlag(HValue::kCanOverflow)) {
+ Label dividend_not_min_int;
+ __ cmpl(dividend, Immediate(kMinInt));
+ __ j(not_zero, ÷nd_not_min_int, Label::kNear);
+ __ cmpl(divisor, Immediate(-1));
+ DeoptimizeIf(zero, instr->environment());
+ __ bind(÷nd_not_min_int);
+ }
+
+ // Sign extend to rdx (= remainder).
+ __ cdq();
+ __ idivl(divisor);
+
+ Label done;
+ __ testl(remainder, remainder);
+ __ j(zero, &done, Label::kNear);
+ __ xorl(remainder, divisor);
+ __ sarl(remainder, Immediate(31));
+ __ addl(result, remainder);
+ __ bind(&done);
+}
void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
@@ -1272,10 +1325,11 @@
}
+// TODO(svenpanne) Refactor this to avoid code duplication with
DoFlooringDivI.
void LCodeGen::DoDivI(LDivI* instr) {
HBinaryOperation* hdiv = instr->hydrogen();
- Register dividend = ToRegister(instr->left());
- Register divisor = ToRegister(instr->right());
+ Register dividend = ToRegister(instr->dividend());
+ Register divisor = ToRegister(instr->divisor());
Register remainder = ToRegister(instr->temp());
Register result = ToRegister(instr->result());
ASSERT(dividend.is(rax));
@@ -1314,15 +1368,7 @@
__ cdq();
__ idivl(divisor);
- if (hdiv->IsMathFloorOfDiv()) {
- Label done;
- __ testl(remainder, remainder);
- __ j(zero, &done, Label::kNear);
- __ xorl(remainder, divisor);
- __ sarl(remainder, Immediate(31));
- __ addl(result, remainder);
- __ bind(&done);
- } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
+ if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deoptimize if remainder is not 0.
__ testl(remainder, remainder);
DeoptimizeIf(not_zero, instr->environment());
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc Tue Apr 1 07:21:31 2014
UTC
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc Tue Apr 1 11:42:42 2014
UTC
@@ -1310,7 +1310,7 @@
}
-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()));
@@ -1322,8 +1322,7 @@
if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
instr->CheckFlag(HValue::kCanOverflow) ||
- (!instr->IsMathFloorOfDiv() &&
- !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
+ !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
result = AssignEnvironment(result);
}
return result;
@@ -1385,6 +1384,24 @@
}
return result;
}
+
+
+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 = UseFixed(instr->left(), rax);
+ LOperand* divisor = UseRegister(instr->right());
+ LOperand* temp = FixedTemp(rdx);
+ LInstruction* result = DefineFixed(new(zone()) LFlooringDivI(
+ dividend, divisor, temp), rax);
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+ instr->CheckFlag(HValue::kCanOverflow)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
+}
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
@@ -1393,7 +1410,7 @@
} else if (instr->right()->IsConstant()) {
return DoFlooringDivByConstI(instr);
} else {
- return DoDivI(instr);
+ return DoFlooringDivI(instr);
}
}
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.h Wed Mar 26 15:51:08 2014
UTC
+++ /branches/bleeding_edge/src/x64/lithium-x64.h Tue Apr 1 11:42:42 2014
UTC
@@ -97,6 +97,7 @@
V(Dummy) \
V(FlooringDivByConstI) \
V(FlooringDivByPowerOf2I) \
+ V(FlooringDivI) \
V(ForInCacheArray) \
V(ForInPrepareMap) \
V(FunctionLiteral) \
@@ -732,14 +733,14 @@
class LDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
public:
- LDivI(LOperand* left, LOperand* right, LOperand* temp) {
- inputs_[0] = left;
- inputs_[1] = right;
+ LDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
+ inputs_[0] = dividend;
+ inputs_[1] = divisor;
temps_[0] = temp;
}
- LOperand* left() { return inputs_[0]; }
- LOperand* right() { return inputs_[1]; }
+ LOperand* dividend() { return inputs_[0]; }
+ LOperand* divisor() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
@@ -794,6 +795,23 @@
};
+class LFlooringDivI V8_FINAL : public LTemplateInstruction<1, 2, 1> {
+ public:
+ LFlooringDivI(LOperand* dividend, LOperand* divisor, LOperand* temp) {
+ inputs_[0] = dividend;
+ inputs_[1] = divisor;
+ temps_[0] = temp;
+ }
+
+ LOperand* dividend() { return inputs_[0]; }
+ LOperand* divisor() { return inputs_[1]; }
+ LOperand* temp() { return temps_[0]; }
+
+ 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) {
@@ -2681,12 +2699,13 @@
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 {
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.