From 4ac9f20601d35c31f563f9a5e710d9495c391fce Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Fri, 18 Feb 2011 14:34:17 +0000 Subject: [PATCH] X64 Crankshaft: Implement MathRound, MathFloor, MathSqrt, and MathPowHalf UnaryMathOperations in optimizing code generator. Remove unneeded bailout on Math.pow(-0, 0.5) from ia32 and x64 platforms - we produce the correct value without bailing out. Review URL: http://codereview.chromium.org/6532054 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6856 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/lithium-codegen-ia32.cc | 5 -- src/ia32/lithium-ia32.cc | 2 +- src/x64/lithium-codegen-x64.cc | 92 ++++++++++++++++++++++++++++++-- src/x64/lithium-x64.cc | 26 ++++++++- 4 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index d85c4761d..478f8a3eb 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2493,11 +2493,6 @@ void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { XMMRegister xmm_scratch = xmm0; XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); - ExternalReference negative_infinity = - ExternalReference::address_of_negative_infinity(); - __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); - __ ucomisd(xmm_scratch, input_reg); - DeoptimizeIf(equal, instr->environment()); __ xorpd(xmm_scratch, xmm_scratch); __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. __ sqrtsd(input_reg, input_reg); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index e1b06d62a..58f7fd4d7 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1223,7 +1223,7 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { case kMathSqrt: return DefineSameAsFirst(result); case kMathPowHalf: - return AssignEnvironment(DefineSameAsFirst(result)); + return DefineSameAsFirst(result); default: UNREACHABLE(); return NULL; diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index e3563d265..65bd1f8d7 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -2097,22 +2097,76 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { - Abort("Unimplemented: %s", "DoMathFloor"); + XMMRegister xmm_scratch = xmm0; + Register output_reg = ToRegister(instr->result()); + XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); + __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. + __ ucomisd(input_reg, xmm_scratch); + + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { + DeoptimizeIf(below_equal, instr->environment()); + } else { + DeoptimizeIf(below, instr->environment()); + } + + // Use truncating instruction (OK because input is positive). + __ cvttsd2si(output_reg, input_reg); + + // Overflow is signalled with minint. + __ cmpl(output_reg, Immediate(0x80000000)); + DeoptimizeIf(equal, instr->environment()); } void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { - Abort("Unimplemented: %s", "DoMathRound"); + const XMMRegister xmm_scratch = xmm0; + Register output_reg = ToRegister(instr->result()); + XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); + + // xmm_scratch = 0.5 + __ movq(kScratchRegister, V8_INT64_C(0x3FE0000000000000), RelocInfo::NONE); + __ movq(xmm_scratch, kScratchRegister); + + // input = input + 0.5 + __ addsd(input_reg, xmm_scratch); + + // We need to return -0 for the input range [-0.5, 0[, otherwise + // compute Math.floor(value + 0.5). + if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { + __ ucomisd(input_reg, xmm_scratch); + DeoptimizeIf(below_equal, instr->environment()); + } else { + // If we don't need to bailout on -0, we check only bailout + // on negative inputs. + __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. + __ ucomisd(input_reg, xmm_scratch); + DeoptimizeIf(below, instr->environment()); + } + + // Compute Math.floor(value + 0.5). + // Use truncating instruction (OK because input is positive). + __ cvttsd2si(output_reg, input_reg); + + // Overflow is signalled with minint. + __ cmpl(output_reg, Immediate(0x80000000)); + DeoptimizeIf(equal, instr->environment()); } void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { - Abort("Unimplemented: %s", "DoMathSqrt"); + XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); + ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); + __ sqrtsd(input_reg, input_reg); } void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { - Abort("Unimplemented: %s", "DoMathPowHalf"); + XMMRegister xmm_scratch = xmm0; + XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); + ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); + __ xorpd(xmm_scratch, xmm_scratch); + __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. + __ sqrtsd(input_reg, input_reg); } @@ -2137,7 +2191,35 @@ void LCodeGen::DoMathSin(LUnaryMathOperation* instr) { void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { - Abort("Unimplemented: %s", "DoUnaryMathOperation"); + switch (instr->op()) { + case kMathAbs: + DoMathAbs(instr); + break; + case kMathFloor: + DoMathFloor(instr); + break; + case kMathRound: + DoMathRound(instr); + break; + case kMathSqrt: + DoMathSqrt(instr); + break; + case kMathPowHalf: + DoMathPowHalf(instr); + break; + case kMathCos: + DoMathCos(instr); + break; + case kMathSin: + DoMathSin(instr); + break; + case kMathLog: + DoMathLog(instr); + break; + + default: + UNREACHABLE(); + } } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index b3287262e..6b514e3ab 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1181,8 +1181,30 @@ LInstruction* LChunkBuilder::DoCallConstantFunction( LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { - Abort("Unimplemented: %s", "DoUnaryMathOperation"); - return NULL; + BuiltinFunctionId op = instr->op(); + if (op == kMathLog || op == kMathSin || op == kMathCos) { + LOperand* input = UseFixedDouble(instr->value(), xmm1); + LUnaryMathOperation* result = new LUnaryMathOperation(input); + return MarkAsCall(DefineFixedDouble(result, xmm1), instr); + } else { + LOperand* input = UseRegisterAtStart(instr->value()); + LUnaryMathOperation* result = new LUnaryMathOperation(input); + switch (op) { + case kMathAbs: + return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); + case kMathFloor: + return AssignEnvironment(DefineAsRegister(result)); + case kMathRound: + return AssignEnvironment(DefineAsRegister(result)); + case kMathSqrt: + return DefineSameAsFirst(result); + case kMathPowHalf: + return DefineSameAsFirst(result); + default: + UNREACHABLE(); + return NULL; + } + } } -- 2.34.1