From c5c8276f59b2b8ca7882129bc8f1c807ea9fe5ef Mon Sep 17 00:00:00 2001 From: "ulan@chromium.org" Date: Fri, 7 Dec 2012 11:29:27 +0000 Subject: [PATCH] Improve double to integer truncation on ARM. BUG=none TEST=none Review URL: https://chromiumcodereview.appspot.com/11412272 Patch from Rodolph Perfetta . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13162 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-codegen-arm.cc | 8 +++----- src/arm/macro-assembler-arm.cc | 32 ++++++++++++++++++++++---------- src/arm/macro-assembler-arm.h | 10 +++++++++- src/arm/stub-cache-arm.cc | 2 +- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 1cfa8e9..53d9981 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -4968,7 +4968,6 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { if (instr->truncating()) { CpuFeatures::Scope scope(VFP2); Register scratch3 = ToRegister(instr->temp2()); - SwVfpRegister single_scratch = double_scratch.low(); ASSERT(!scratch3.is(input_reg) && !scratch3.is(scratch1) && !scratch3.is(scratch2)); @@ -4990,7 +4989,7 @@ void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { __ EmitECMATruncate(input_reg, double_scratch2, - single_scratch, + double_scratch, scratch1, scratch2, scratch3); @@ -5072,20 +5071,19 @@ void LCodeGen::DoDoubleToI(LDoubleToI* instr) { Register scratch1 = scratch0(); Register scratch2 = ToRegister(instr->temp()); DwVfpRegister double_input = ToDoubleRegister(instr->value()); + DwVfpRegister double_scratch = double_scratch0(); Label done; if (instr->truncating()) { Register scratch3 = ToRegister(instr->temp2()); - SwVfpRegister single_scratch = double_scratch0().low(); __ EmitECMATruncate(result_reg, double_input, - single_scratch, + double_scratch, scratch1, scratch2, scratch3); } else { - DwVfpRegister double_scratch = double_scratch0(); __ EmitVFPTruncate(kRoundToMinusInf, result_reg, double_input, diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 067a05d..33b557e 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -2490,6 +2490,20 @@ void MacroAssembler::ConvertToInt32(Register source, } +void MacroAssembler::TryFastDoubleToInt32(Register result, + DwVfpRegister double_input, + DwVfpRegister double_scratch, + Label* done) { + ASSERT(!double_input.is(double_scratch)); + + vcvt_s32_f64(double_scratch.low(), double_input); + vmov(result, double_scratch.low()); + vcvt_f64_s32(double_scratch, double_scratch.low()); + VFPCompareAndSetFlags(double_input, double_scratch); + b(eq, done); +} + + void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode, Register result, DwVfpRegister double_input, @@ -2505,11 +2519,7 @@ void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode, Label done; // Test for values that can be exactly represented as a signed 32-bit integer. - vcvt_s32_f64(double_scratch.low(), double_input); - vmov(result, double_scratch.low()); - vcvt_f64_s32(double_scratch, double_scratch.low()); - VFPCompareAndSetFlags(double_input, double_scratch); - b(eq, &done); + TryFastDoubleToInt32(result, double_input, double_scratch, &done); // Convert to integer, respecting rounding mode. int32_t check_inexact_conversion = @@ -2626,7 +2636,7 @@ void MacroAssembler::EmitOutOfInt32RangeTruncate(Register result, void MacroAssembler::EmitECMATruncate(Register result, DwVfpRegister double_input, - SwVfpRegister single_scratch, + DwVfpRegister double_scratch, Register scratch, Register input_high, Register input_low) { @@ -2637,16 +2647,18 @@ void MacroAssembler::EmitECMATruncate(Register result, ASSERT(!scratch.is(result) && !scratch.is(input_high) && !scratch.is(input_low)); - ASSERT(!single_scratch.is(double_input.low()) && - !single_scratch.is(double_input.high())); + ASSERT(!double_input.is(double_scratch)); Label done; + // Test for values that can be exactly represented as a signed 32-bit integer. + TryFastDoubleToInt32(result, double_input, double_scratch, &done); + // Clear cumulative exception flags. ClearFPSCRBits(kVFPExceptionMask, scratch); // Try a conversion to a signed integer. - vcvt_s32_f64(single_scratch, double_input); - vmov(result, single_scratch); + vcvt_s32_f64(double_scratch.low(), double_input); + vmov(result, double_scratch.low()); // Retrieve he FPSCR. vmrs(scratch); // Check for overflow and NaNs. diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 50c298b..5321a0d 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -959,6 +959,14 @@ class MacroAssembler: public Assembler { DwVfpRegister double_scratch, Label *not_int32); + // Try to convert a double to a signed 32-bit integer. If the double value + // can be exactly represented as an integer, the code jumps to 'done' and + // 'result' contains the integer value. Otherwise, the code falls through. + void TryFastDoubleToInt32(Register result, + DwVfpRegister double_input, + DwVfpRegister double_scratch, + Label* done); + // Truncates a double using a specific rounding mode, and writes the value // to the result register. // Clears the z flag (ne condition) if an overflow occurs. @@ -989,7 +997,7 @@ class MacroAssembler: public Assembler { // Exits with 'result' holding the answer and all other registers clobbered. void EmitECMATruncate(Register result, DwVfpRegister double_input, - SwVfpRegister single_scratch, + DwVfpRegister double_scratch, Register scratch, Register scratch2, Register scratch3); diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index e79c520..dd5db30 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -3836,7 +3836,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( // not include -kHeapObjectTag into it. __ sub(r5, value, Operand(kHeapObjectTag)); __ vldr(d0, r5, HeapNumber::kValueOffset); - __ EmitECMATruncate(r5, d0, s2, r6, r7, r9); + __ EmitECMATruncate(r5, d0, d1, r6, r7, r9); switch (elements_kind) { case EXTERNAL_BYTE_ELEMENTS: -- 2.7.4