From e1448ebd343da38a357336107a5af5da9a7c6581 Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Mon, 21 Feb 2011 11:32:28 +0000 Subject: [PATCH] X64 Crankshaft: Add ModI and ModT to x64 optimizing compiler. Review URL: http://codereview.chromium.org/6548005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/x64/lithium-codegen-x64.cc | 37 ++++++++++++++++++++++++++++++++++++- src/x64/lithium-x64.cc | 28 ++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index e695eb8..b04535d 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -683,7 +683,42 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 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); + } } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index 5bddc7e..60af65c 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1318,8 +1318,32 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { 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); + } } -- 2.7.4