Reviewers: Rico,

Description:
X64 Crankshaft: Add ModI and ModT to x64 optimizing compiler.

Please review this at http://codereview.chromium.org/6548005/

SVN Base: http://v8.googlecode.com/svn/branches/bleeding_edge/

Affected files:
  M     src/x64/lithium-codegen-x64.cc
  M     src/x64/lithium-x64.cc


Index: src/x64/lithium-codegen-x64.cc
===================================================================
--- src/x64/lithium-codegen-x64.cc      (revision 6859)
+++ src/x64/lithium-codegen-x64.cc      (working copy)
@@ -683,7 +683,42 @@


 void LCodeGen::DoModI(LModI* instr) {
-  Abort("Unimplemented: %s", "DoModI");
+  LOperand* right = instr->InputAt(1);
+  ASSERT(ToRegister(instr->result()).is(rdx));
+  ASSERT(ToRegister(instr->InputAt(0)).is(rax));
+  ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
+  ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
+
+  Register right_reg = ToRegister(right);
+
+  // Check for x % 0.
+  if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+    __ testl(right_reg, right_reg);
+    DeoptimizeIf(zero, instr->environment());
+  }
+
+ // Sign extend eax to edx. (We are using only the low 32 bits of the values.)
+  __ cdq();
+
+  // Check for (0 % -x) that will produce negative zero.
+  if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+    NearLabel positive_left;
+    NearLabel done;
+    __ testl(rax, rax);
+    __ j(not_sign, &positive_left);
+    __ idivl(right_reg);
+
+    // Test the remainder for 0, because then the result would be -0.
+    __ testl(rdx, rdx);
+    __ j(not_zero, &done);
+
+    DeoptimizeIf(no_condition, instr->environment());
+    __ bind(&positive_left);
+    __ idivl(right_reg);
+    __ bind(&done);
+  } else {
+    __ idivl(right_reg);
+  }
 }


Index: src/x64/lithium-x64.cc
===================================================================
--- src/x64/lithium-x64.cc      (revision 6859)
+++ src/x64/lithium-x64.cc      (working copy)
@@ -1318,8 +1318,32 @@


 LInstruction* LChunkBuilder::DoMod(HMod* instr) {
-  Abort("Unimplemented: %s", "DoMod");
-  return NULL;
+  if (instr->representation().IsInteger32()) {
+    ASSERT(instr->left()->representation().IsInteger32());
+    ASSERT(instr->right()->representation().IsInteger32());
+ // The temporary operand is necessary to ensure that right is not allocated
+    // into edx.
+    LOperand* temp = FixedTemp(rdx);
+    LOperand* value = UseFixed(instr->left(), rax);
+    LOperand* divisor = UseRegister(instr->right());
+    LModI* mod = new LModI(value, divisor, temp);
+    LInstruction* result = DefineFixed(mod, rdx);
+    return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+            instr->CheckFlag(HValue::kCanBeDivByZero))
+        ? AssignEnvironment(result)
+        : result;
+  } else if (instr->representation().IsTagged()) {
+    return DoArithmeticT(Token::MOD, instr);
+  } else {
+    ASSERT(instr->representation().IsDouble());
+    // We call a C function for double modulo. It can't trigger a GC.
+    // We need to use fixed result register for the call.
+    // TODO(fschneider): Allow any register as input registers.
+    LOperand* left = UseFixedDouble(instr->left(), xmm1);
+    LOperand* right = UseFixedDouble(instr->right(), xmm2);
+    LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
+    return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
+  }
 }




--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to