From 1bfa62204302de66dcf35447e1ae4ff288bc144c Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Mon, 5 Dec 2011 15:58:25 +0000 Subject: [PATCH] Refactor MathPowHalf on ia32. BUG=v8:397, v8:1848 TEST=regress-397.js Review URL: http://codereview.chromium.org/8806010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10157 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/lithium-codegen-ia32.cc | 39 +++++++++++++++++++-------------------- src/ia32/lithium-codegen-ia32.h | 1 - src/ia32/lithium-ia32.cc | 13 +++++++++++-- src/ia32/lithium-ia32.h | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 31d8f5c..2925dcd 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -2934,31 +2934,33 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { } -void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { +void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { XMMRegister xmm_scratch = xmm0; XMMRegister input_reg = ToDoubleRegister(instr->value()); + Register scratch = ToRegister(instr->temp()); ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); - Label return_infinity, done; - // Check base for +/- infinity. - __ push(ecx); // TODO(1848): reserve this register. - __ mov(ecx, factory()->infinity_value()); - __ ucomisd(input_reg, FieldOperand(ecx, HeapNumber::kValueOffset)); - __ j(equal, &return_infinity, Label::kNear); - __ xorps(xmm_scratch, xmm_scratch); - __ subsd(xmm_scratch, input_reg); - __ ucomisd(xmm_scratch, FieldOperand(ecx, HeapNumber::kValueOffset)); - __ j(equal, &return_infinity, Label::kNear); + // Note that according to ECMA-262 15.8.2.13: + // Math.pow(-Infinity, 0.5) == Infinity + // Math.sqrt(-Infinity) == NaN + Label done, sqrt; + // Check base for -Infinity. According to IEEE-754, single-precision + // -Infinity has the highest 9 bits set and the lowest 23 bits cleared. + __ mov(scratch, 0xFF800000); + __ movd(xmm_scratch, scratch); + __ cvtss2sd(xmm_scratch, xmm_scratch); + __ ucomisd(input_reg, xmm_scratch); + __ j(not_equal, &sqrt, Label::kNear); + // If input is -Infinity, return Infinity. + __ xorps(input_reg, input_reg); + __ subsd(input_reg, xmm_scratch); + __ jmp(&done, Label::kNear); - __ pop(ecx); + // Square root. + __ bind(&sqrt); __ xorps(xmm_scratch, xmm_scratch); __ addsd(input_reg, xmm_scratch); // Convert -0 to +0. __ sqrtsd(input_reg, input_reg); - __ jmp(&done, Label::kNear); - - __ bind(&return_infinity); - __ movdbl(input_reg, FieldOperand(ecx, HeapNumber::kValueOffset)); - __ pop(ecx); __ bind(&done); } @@ -3062,9 +3064,6 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) { case kMathSqrt: DoMathSqrt(instr); break; - case kMathPowHalf: - DoMathPowHalf(instr); - break; case kMathCos: DoMathCos(instr); break; diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index 9d1a4f7..0dbb8b0 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -239,7 +239,6 @@ class LCodeGen BASE_EMBEDDED { void DoMathFloor(LUnaryMathOperation* instr); void DoMathRound(LUnaryMathOperation* instr); void DoMathSqrt(LUnaryMathOperation* instr); - void DoMathPowHalf(LUnaryMathOperation* instr); void DoMathLog(LUnaryMathOperation* instr); void DoMathTan(LUnaryMathOperation* instr); void DoMathCos(LUnaryMathOperation* instr); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 4e5f278..ecb490d 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -298,6 +298,12 @@ void LUnaryMathOperation::PrintDataTo(StringStream* stream) { } +void LMathPowHalf::PrintDataTo(StringStream* stream) { + stream->Add("/pow_half "); + InputAt(0)->PrintTo(stream); +} + + void LLoadContextSlot::PrintDataTo(StringStream* stream) { InputAt(0)->PrintTo(stream); stream->Add("[%d]", slot_index()); @@ -1184,6 +1190,11 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { } else { LOperand* input = UseRegisterAtStart(instr->value()); LOperand* context = UseAny(instr->context()); // Deferred use by MathAbs. + if (op == kMathPowHalf) { + LOperand* temp = TempRegister(); + LMathPowHalf* result = new(zone()) LMathPowHalf(context, input, temp); + return DefineSameAsFirst(result); + } LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(context, input); switch (op) { @@ -1195,8 +1206,6 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { return AssignEnvironment(DefineAsRegister(result)); case kMathSqrt: return DefineSameAsFirst(result); - case kMathPowHalf: - return DefineSameAsFirst(result); default: UNREACHABLE(); return NULL; diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 5170647..7e126ff 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -123,6 +123,7 @@ class LCodeGen; V(LoadNamedField) \ V(LoadNamedFieldPolymorphic) \ V(LoadNamedGeneric) \ + V(MathPowHalf) \ V(ModI) \ V(MulI) \ V(NumberTagD) \ @@ -582,6 +583,24 @@ class LUnaryMathOperation: public LTemplateInstruction<1, 2, 0> { }; +class LMathPowHalf: public LTemplateInstruction<1, 2, 1> { + public: + LMathPowHalf(LOperand* context, LOperand* value, LOperand* temp) { + inputs_[1] = context; + inputs_[0] = value; + temps_[0] = temp; + } + + LOperand* context() { return inputs_[1]; } + LOperand* value() { return inputs_[0]; } + LOperand* temp() { return temps_[0]; } + + DECLARE_CONCRETE_INSTRUCTION(MathPowHalf, "math-pow-half") + + virtual void PrintDataTo(StringStream* stream); +}; + + class LCmpObjectEqAndBranch: public LControlInstruction<2, 0> { public: LCmpObjectEqAndBranch(LOperand* left, LOperand* right) { -- 2.7.4