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, &dividend_not_zero, Label::kNear);
+    __ test(divisor, divisor);
+    DeoptimizeIf(sign, instr->environment());
+    __ bind(&dividend_not_zero);
+  }
+
+  // Check for (kMinInt / -1).
+  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
+    Label dividend_not_min_int;
+    __ cmp(dividend, kMinInt);
+    __ j(not_zero, &dividend_not_min_int, Label::kNear);
+    __ cmp(divisor, -1);
+    DeoptimizeIf(zero, instr->environment());
+    __ bind(&dividend_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, &dividend_not_zero, Label::kNear);
+    __ testl(divisor, divisor);
+    DeoptimizeIf(sign, instr->environment());
+    __ bind(&dividend_not_zero);
+  }
+
+  // Check for (kMinInt / -1).
+  if (hdiv->CheckFlag(HValue::kCanOverflow)) {
+    Label dividend_not_min_int;
+    __ cmpl(dividend, Immediate(kMinInt));
+    __ j(not_zero, &dividend_not_min_int, Label::kNear);
+    __ cmpl(divisor, Immediate(-1));
+    DeoptimizeIf(zero, instr->environment());
+    __ bind(&dividend_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.

Reply via email to