From: jkummerow@chromium.org Date: Thu, 29 Nov 2012 09:09:39 +0000 (+0000) Subject: MIPS: ARM: Fast path for integer inputs to EmitVFPTruncate X-Git-Tag: upstream/4.7.83~15540 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=273b97f9b4e7f69b1e30f5d11be9f7f410068b8b;p=platform%2Fupstream%2Fv8.git MIPS: ARM: Fast path for integer inputs to EmitVFPTruncate Port r12676 (7d5e7e81) BUG= TEST= Review URL: https://codereview.chromium.org/11308134 Patch from Akos Palfi . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13086 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index 0e4d37b..aa27f6a 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -816,6 +816,7 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, Register object, Destination destination, DoubleRegister double_dst, + DoubleRegister double_scratch, Register dst1, Register dst2, Register heap_number_map, @@ -851,9 +852,10 @@ void FloatingPointHelper::LoadNumberAsInt32Double(MacroAssembler* masm, Register except_flag = scratch2; __ EmitFPUTruncate(kRoundToZero, - single_scratch, - double_dst, scratch1, + double_dst, + at, + double_scratch, except_flag, kCheckForInexactConversion); @@ -895,7 +897,8 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, Register scratch1, Register scratch2, Register scratch3, - DoubleRegister double_scratch, + DoubleRegister double_scratch0, + DoubleRegister double_scratch1, Label* not_int32) { ASSERT(!dst.is(object)); ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object)); @@ -918,22 +921,19 @@ void FloatingPointHelper::LoadNumberAsInt32(MacroAssembler* masm, if (CpuFeatures::IsSupported(FPU)) { CpuFeatures::Scope scope(FPU); // Load the double value. - __ ldc1(double_scratch, FieldMemOperand(object, HeapNumber::kValueOffset)); + __ ldc1(double_scratch0, FieldMemOperand(object, HeapNumber::kValueOffset)); - FPURegister single_scratch = double_scratch.low(); Register except_flag = scratch2; __ EmitFPUTruncate(kRoundToZero, - single_scratch, - double_scratch, + dst, + double_scratch0, scratch1, + double_scratch1, except_flag, kCheckForInexactConversion); // Jump to not_int32 if the operation did not succeed. __ Branch(not_int32, ne, except_flag, Operand(zero_reg)); - // Get the result in the destination register. - __ mfc1(dst, single_scratch); - } else { // Load the double value in the destination registers. __ lw(scratch2, FieldMemOperand(object, HeapNumber::kExponentOffset)); @@ -2955,6 +2955,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { right, destination, f14, + f16, a2, a3, heap_number_map, @@ -2966,6 +2967,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { left, destination, f12, + f16, t0, t1, heap_number_map, @@ -3002,9 +3004,10 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { Register except_flag = scratch2; __ EmitFPUTruncate(kRoundToZero, - single_scratch, - f10, scratch1, + f10, + at, + f16, except_flag); if (result_type_ <= BinaryOpIC::INT32) { @@ -3013,7 +3016,6 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { } // Check if the result fits in a smi. - __ mfc1(scratch1, single_scratch); __ Addu(scratch2, scratch1, Operand(0x40000000)); // If not try to return a heap number. __ Branch(&return_heap_number, lt, scratch2, Operand(zero_reg)); @@ -3108,6 +3110,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { scratch2, scratch3, f0, + f2, &transition); FloatingPointHelper::LoadNumberAsInt32(masm, right, @@ -3117,6 +3120,7 @@ void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { scratch2, scratch3, f0, + f2, &transition); // The ECMA-262 standard specifies that, for shift operations, only the @@ -3683,9 +3687,10 @@ void MathPowStub::Generate(MacroAssembler* masm) { Label int_exponent_convert; // Detect integer exponents stored as double. __ EmitFPUTruncate(kRoundToMinusInf, - single_scratch, - double_exponent, scratch, + double_exponent, + at, + double_scratch, scratch2, kCheckForInexactConversion); // scratch2 == 0 means there was no conversion error. @@ -3743,7 +3748,7 @@ void MathPowStub::Generate(MacroAssembler* masm) { __ push(ra); { AllowExternalCallThatCantCauseGC scope(masm); - __ PrepareCallCFunction(0, 2, scratch); + __ PrepareCallCFunction(0, 2, scratch2); __ SetCallCDoubleArguments(double_base, double_exponent); __ CallCFunction( ExternalReference::power_double_double_function(masm->isolate()), @@ -3754,7 +3759,6 @@ void MathPowStub::Generate(MacroAssembler* masm) { __ jmp(&done); __ bind(&int_exponent_convert); - __ mfc1(scratch, single_scratch); } // Calculate power with integer exponent. diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h index bb36d22..b560c63 100644 --- a/src/mips/code-stubs-mips.h +++ b/src/mips/code-stubs-mips.h @@ -657,6 +657,7 @@ class FloatingPointHelper : public AllStatic { Register object, Destination destination, FPURegister double_dst, + FPURegister double_scratch, Register dst1, Register dst2, Register heap_number_map, @@ -678,7 +679,8 @@ class FloatingPointHelper : public AllStatic { Register scratch1, Register scratch2, Register scratch3, - FPURegister double_scratch, + FPURegister double_scratch0, + FPURegister double_scratch1, Label* not_int32); // Generate non FPU code to check if a double can be exactly represented by a diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 56a89e0..cebcc7e 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -3262,22 +3262,19 @@ void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { DoubleRegister input = ToDoubleRegister(instr->value()); Register result = ToRegister(instr->result()); - FPURegister single_scratch = double_scratch0().low(); Register scratch1 = scratch0(); Register except_flag = ToRegister(instr->temp()); __ EmitFPUTruncate(kRoundToMinusInf, - single_scratch, + result, input, scratch1, + double_scratch0(), except_flag); // Deopt if the operation did not succeed. DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); - // Load the result. - __ mfc1(result, single_scratch); - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { // Test for -0. Label done; @@ -3293,6 +3290,7 @@ void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { DoubleRegister input = ToDoubleRegister(instr->value()); Register result = ToRegister(instr->result()); + DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); Register scratch = scratch0(); Label done, check_sign_on_zero; @@ -3344,17 +3342,15 @@ void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { } Register except_flag = scratch; - __ EmitFPUTruncate(kRoundToMinusInf, - double_scratch0().low(), - double_scratch0(), result, + double_scratch0(), + at, + double_scratch1, except_flag); DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); - __ mfc1(result, double_scratch0().low()); - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { // Test for -0. __ Branch(&done, ne, result, Operand(zero_reg)); @@ -4391,7 +4387,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { Register scratch1 = scratch0(); Register scratch2 = ToRegister(instr->temp()); DoubleRegister double_scratch = double_scratch0(); - FPURegister single_scratch = double_scratch.low(); + DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp3()); ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2)); ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1)); @@ -4407,7 +4403,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { if (instr->truncating()) { Register scratch3 = ToRegister(instr->temp2()); - DoubleRegister double_scratch2 = ToDoubleRegister(instr->temp3()); + FPURegister single_scratch = double_scratch.low(); ASSERT(!scratch3.is(input_reg) && !scratch3.is(scratch1) && !scratch3.is(scratch2)); @@ -4442,18 +4438,16 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { Register except_flag = scratch2; __ EmitFPUTruncate(kRoundToZero, - single_scratch, + input_reg, double_scratch, scratch1, + double_scratch2, except_flag, kCheckForInexactConversion); // Deopt if the operation did not succeed. DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); - // Load the result. - __ mfc1(input_reg, single_scratch); - if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { __ Branch(&done, ne, input_reg, Operand(zero_reg)); @@ -4515,10 +4509,10 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { Register scratch1 = scratch0(); Register scratch2 = ToRegister(instr->temp()); DoubleRegister double_input = ToDoubleRegister(instr->value()); - FPURegister single_scratch = double_scratch0().low(); if (instr->truncating()) { Register scratch3 = ToRegister(instr->temp2()); + FPURegister single_scratch = double_scratch0().low(); __ EmitECMATruncate(result_reg, double_input, single_scratch, @@ -4529,17 +4523,15 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { Register except_flag = scratch2; __ EmitFPUTruncate(kRoundToMinusInf, - single_scratch, + result_reg, double_input, scratch1, + double_scratch0(), except_flag, kCheckForInexactConversion); // Deopt if the operation did not succeed (except_flag != 0). DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); - - // Load the result. - __ mfc1(result_reg, single_scratch); } } diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc index 2d2a413..ebd54f5 100644 --- a/src/mips/lithium-mips.cc +++ b/src/mips/lithium-mips.cc @@ -1049,7 +1049,9 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { return DefineFixedDouble(result, f4); } else { LOperand* input = UseRegisterAtStart(instr->value()); - LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; + + LOperand* temp = (op == kMathRound) ? FixedTemp(f6) : + (op == kMathFloor) ? TempRegister() : NULL; LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp); switch (op) { case kMathAbs: @@ -1566,8 +1568,7 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { LOperand* temp1 = TempRegister(); LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() : NULL; - LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(f22) - : NULL; + LOperand* temp3 = FixedTemp(f22); res = DefineSameAsFirst(new(zone()) LTaggedToI(value, temp1, temp2, diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index 926b3bf..6105e71 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -1395,49 +1395,68 @@ void MacroAssembler::ConvertToInt32(Register source, void MacroAssembler::EmitFPUTruncate(FPURoundingMode rounding_mode, - FPURegister result, + Register result, DoubleRegister double_input, - Register scratch1, + Register scratch, + DoubleRegister double_scratch, Register except_flag, CheckForInexactConversion check_inexact) { + ASSERT(!result.is(scratch)); + ASSERT(!double_input.is(double_scratch)); + ASSERT(!except_flag.is(scratch)); + ASSERT(CpuFeatures::IsSupported(FPU)); CpuFeatures::Scope scope(FPU); + Label done; + + // Clear the except flag (0 = no exception) + mov(except_flag, zero_reg); + + // Test for values that can be exactly represented as a signed 32-bit integer. + cvt_w_d(double_scratch, double_input); + mfc1(result, double_scratch); + cvt_d_w(double_scratch, double_scratch); + BranchF(&done, NULL, eq, double_input, double_scratch); int32_t except_mask = kFCSRFlagMask; // Assume interested in all exceptions. if (check_inexact == kDontCheckForInexactConversion) { - // Ingore inexact exceptions. + // Ignore inexact exceptions. except_mask &= ~kFCSRInexactFlagMask; } // Save FCSR. - cfc1(scratch1, FCSR); + cfc1(scratch, FCSR); // Disable FPU exceptions. ctc1(zero_reg, FCSR); // Do operation based on rounding mode. switch (rounding_mode) { case kRoundToNearest: - Round_w_d(result, double_input); + Round_w_d(double_scratch, double_input); break; case kRoundToZero: - Trunc_w_d(result, double_input); + Trunc_w_d(double_scratch, double_input); break; case kRoundToPlusInf: - Ceil_w_d(result, double_input); + Ceil_w_d(double_scratch, double_input); break; case kRoundToMinusInf: - Floor_w_d(result, double_input); + Floor_w_d(double_scratch, double_input); break; } // End of switch-statement. // Retrieve FCSR. cfc1(except_flag, FCSR); // Restore FCSR. - ctc1(scratch1, FCSR); + ctc1(scratch, FCSR); + // Move the converted value into the result register. + mfc1(result, double_scratch); // Check for fpu exceptions. And(except_flag, except_flag, Operand(except_mask)); + + bind(&done); } diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index ada3184..46f3a90 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -753,14 +753,16 @@ class MacroAssembler: public Assembler { FPURegister double_scratch, Label *not_int32); - // Truncates a double using a specific rounding mode. + // Truncates a double using a specific rounding mode, and writes the value + // to the result register. // The except_flag will contain any exceptions caused by the instruction. - // If check_inexact is kDontCheckForInexactConversion, then the inexacat + // If check_inexact is kDontCheckForInexactConversion, then the inexact // exception is masked. void EmitFPUTruncate(FPURoundingMode rounding_mode, - FPURegister result, + Register result, DoubleRegister double_input, - Register scratch1, + Register scratch, + DoubleRegister double_scratch, Register except_flag, CheckForInexactConversion check_inexact = kDontCheckForInexactConversion); diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index 326cba7..57adc65 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -3695,6 +3695,7 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm, Register scratch0, Register scratch1, FPURegister double_scratch0, + FPURegister double_scratch1, Label* fail) { if (CpuFeatures::IsSupported(FPU)) { CpuFeatures::Scope scope(FPU); @@ -3710,15 +3711,15 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm, DONT_DO_SMI_CHECK); __ ldc1(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset)); __ EmitFPUTruncate(kRoundToZero, - double_scratch0, - double_scratch0, scratch0, + double_scratch0, + at, + double_scratch1, scratch1, kCheckForInexactConversion); __ Branch(fail, ne, scratch1, Operand(zero_reg)); - __ mfc1(scratch0, double_scratch0); __ SmiTagCheckOverflow(key, scratch0, scratch1); __ BranchOnOverflow(fail, scratch1); __ bind(&key_ok); @@ -3746,7 +3747,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( // have been verified by the caller to not be a smi. // Check that the key is a smi or a heap number convertible to a smi. - GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic); + GenerateSmiKeyCheck(masm, key, t0, t1, f2, f4, &miss_force_generic); __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); // a3: elements array @@ -4088,7 +4089,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( // have been verified by the caller to not be a smi. // Check that the key is a smi or a heap number convertible to a smi. - GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic); + GenerateSmiKeyCheck(masm, key, t0, t1, f2, f4, &miss_force_generic); __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); @@ -4477,7 +4478,7 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { // have been verified by the caller to not be a smi. // Check that the key is a smi or a heap number convertible to a smi. - GenerateSmiKeyCheck(masm, a0, t0, t1, f2, &miss_force_generic); + GenerateSmiKeyCheck(masm, a0, t0, t1, f2, f4, &miss_force_generic); // Get the elements array. __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); @@ -4528,7 +4529,7 @@ void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( // have been verified by the caller to not be a smi. // Check that the key is a smi or a heap number convertible to a smi. - GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic); + GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, f4, &miss_force_generic); // Get the elements array. __ lw(elements_reg, @@ -4602,7 +4603,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( // have been verified by the caller to not be a smi. // Check that the key is a smi or a heap number convertible to a smi. - GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic); + GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, f4, &miss_force_generic); if (IsFastSmiElementsKind(elements_kind)) { __ JumpIfNotSmi(value_reg, &transition_elements_kind); @@ -4771,7 +4772,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( // have been verified by the caller to not be a smi. // Check that the key is a smi or a heap number convertible to a smi. - GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic); + GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, f4, &miss_force_generic); __ lw(elements_reg, FieldMemOperand(receiver_reg, JSObject::kElementsOffset));