Revision: 12676
Author:   [email protected]
Date:     Mon Oct  8 05:50:15 2012
Log:      ARM: Fast path for integer inputs to EmitVFPTruncate

BUG=none
TEST=none

Review URL: https://codereview.chromium.org/11049025
Patch from Martyn Capewell <[email protected]>.
http://code.google.com/p/v8/source/detail?r=12676

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/code-stubs-arm.h
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.h
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Sep 27 04:31:26 2012 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Mon Oct 8 05:50:15 2012
@@ -826,6 +826,7 @@
                                                   Register object,
                                                   Destination destination,
                                                   DwVfpRegister double_dst,
+ DwVfpRegister double_scratch,
                                                   Register dst1,
                                                   Register dst2,
                                                   Register heap_number_map,
@@ -863,10 +864,10 @@
     __ vldr(double_dst, scratch1, HeapNumber::kValueOffset);

     __ EmitVFPTruncate(kRoundToZero,
-                       single_scratch,
+                       scratch1,
                        double_dst,
-                       scratch1,
                        scratch2,
+                       double_scratch,
                        kCheckForInexactConversion);

     // Jump to not_int32 if the operation did not succeed.
@@ -906,7 +907,8 @@
                                             Register scratch1,
                                             Register scratch2,
                                             Register scratch3,
-                                            DwVfpRegister double_scratch,
+                                            DwVfpRegister double_scratch0,
+                                            DwVfpRegister double_scratch1,
                                             Label* not_int32) {
   ASSERT(!dst.is(object));
ASSERT(!scratch1.is(object) && !scratch2.is(object) && !scratch3.is(object));
@@ -929,23 +931,20 @@
   // Convert the floating point value to a 32-bit integer.
   if (CpuFeatures::IsSupported(VFP2)) {
     CpuFeatures::Scope scope(VFP2);
-    SwVfpRegister single_scratch = double_scratch.low();
+
     // Load the double value.
     __ sub(scratch1, object, Operand(kHeapObjectTag));
-    __ vldr(double_scratch, scratch1, HeapNumber::kValueOffset);
+    __ vldr(double_scratch0, scratch1, HeapNumber::kValueOffset);

     __ EmitVFPTruncate(kRoundToZero,
-                       single_scratch,
-                       double_scratch,
+                       dst,
+                       double_scratch0,
                        scratch1,
-                       scratch2,
+                       double_scratch1,
                        kCheckForInexactConversion);

     // Jump to not_int32 if the operation did not succeed.
     __ b(ne, not_int32);
-    // Get the result in the destination register.
-    __ vmov(dst, single_scratch);
-
   } else {
     // Load the double value in the destination registers.
     __ ldr(scratch1, FieldMemOperand(object, HeapNumber::kExponentOffset));
@@ -2850,7 +2849,6 @@
   Register scratch1 = r7;
   Register scratch2 = r9;
   DwVfpRegister double_scratch = d0;
-  SwVfpRegister single_scratch = s3;

   Register heap_number_result = no_reg;
   Register heap_number_map = r6;
@@ -2888,6 +2886,7 @@
                                                    right,
                                                    destination,
                                                    d7,
+                                                   d8,
                                                    r2,
                                                    r3,
                                                    heap_number_map,
@@ -2899,6 +2898,7 @@
                                                    left,
                                                    destination,
                                                    d6,
+                                                   d8,
                                                    r4,
                                                    r5,
                                                    heap_number_map,
@@ -2934,10 +2934,10 @@
           // transition.

           __ EmitVFPTruncate(kRoundToZero,
-                             single_scratch,
+                             scratch1,
                              d5,
-                             scratch1,
-                             scratch2);
+                             scratch2,
+                             d8);

           if (result_type_ <= BinaryOpIC::INT32) {
             // If the ne condition is set, result does
@@ -2946,7 +2946,6 @@
           }

           // Check if the result fits in a smi.
-          __ vmov(scratch1, single_scratch);
           __ add(scratch2, scratch1, Operand(0x40000000), SetCC);
           // If not try to return a heap number.
           __ b(mi, &return_heap_number);
@@ -3041,6 +3040,7 @@
                                              scratch2,
                                              scratch3,
                                              d0,
+                                             d1,
                                              &transition);
       FloatingPointHelper::LoadNumberAsInt32(masm,
                                              right,
@@ -3050,6 +3050,7 @@
                                              scratch2,
                                              scratch3,
                                              d0,
+                                             d1,
                                              &transition);

// The ECMA-262 standard specifies that, for shift operations, only the
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.h Wed Jul 25 08:26:16 2012 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.h Mon Oct 8 05:50:15 2012
@@ -773,6 +773,7 @@
                                       Register object,
                                       Destination destination,
                                       DwVfpRegister double_dst,
+                                      DwVfpRegister double_scratch,
                                       Register dst1,
                                       Register dst2,
                                       Register heap_number_map,
@@ -794,7 +795,8 @@
                                 Register scratch1,
                                 Register scratch2,
                                 Register scratch3,
-                                DwVfpRegister double_scratch,
+                                DwVfpRegister double_scratch0,
+                                DwVfpRegister double_scratch1,
                                 Label* not_int32);

// Generate non VFP3 code to check if a double can be exactly represented by a
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Wed Sep 19 01:13:46 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Mon Oct  8 05:50:15 2012
@@ -1040,7 +1040,8 @@
     return DefineFixedDouble(result, d2);
   } else {
     LOperand* input = UseRegisterAtStart(instr->value());
-    LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL;
+
+    LOperand* temp = (op == kMathRound) ? FixedTemp(d3) : NULL;
LUnaryMathOperation* result = new(zone()) LUnaryMathOperation(input, temp);
     switch (op) {
       case kMathAbs:
@@ -1616,8 +1617,7 @@
         LOperand* temp1 = TempRegister();
         LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister()
                                                       : NULL;
-        LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11)
-                                                      : NULL;
+        LOperand* temp3 = FixedTemp(d11);
         res = DefineSameAsFirst(new(zone()) LTaggedToI(value,
                                                        temp1,
                                                        temp2,
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Oct 2 09:48:45 2012 +++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Mon Oct 8 05:50:15 2012
@@ -3499,27 +3499,22 @@
 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) {
   DoubleRegister input = ToDoubleRegister(instr->value());
   Register result = ToRegister(instr->result());
-  SwVfpRegister single_scratch = double_scratch0().low();
-  Register scratch1 = scratch0();
-  Register scratch2 = ToRegister(instr->temp());
+  Register scratch = scratch0();

   __ EmitVFPTruncate(kRoundToMinusInf,
-                     single_scratch,
+                     result,
                      input,
-                     scratch1,
-                     scratch2);
+                     scratch,
+                     double_scratch0());
   DeoptimizeIf(ne, instr->environment());

-  // Move the result back to general purpose register r0.
-  __ vmov(result, single_scratch);
-
   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
     // Test for -0.
     Label done;
     __ cmp(result, Operand(0));
     __ b(ne, &done);
-    __ vmov(scratch1, input.high());
-    __ tst(scratch1, Operand(HeapNumber::kSignMask));
+    __ vmov(scratch, input.high());
+    __ tst(scratch, Operand(HeapNumber::kSignMask));
     DeoptimizeIf(ne, instr->environment());
     __ bind(&done);
   }
@@ -3529,6 +3524,7 @@
 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
   DoubleRegister input = ToDoubleRegister(instr->value());
   Register result = ToRegister(instr->result());
+  DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
   Register scratch = scratch0();
   Label done, check_sign_on_zero;

@@ -3571,12 +3567,11 @@
   }

   __ EmitVFPTruncate(kRoundToMinusInf,
-                     double_scratch0().low(),
+                     result,
                      double_scratch0(),
-                     result,
-                     scratch);
+                     scratch,
+                     double_scratch1);
   DeoptimizeIf(ne, instr->environment());
-  __ vmov(result, double_scratch0().low());

   if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
     // Test for -0.
@@ -4602,7 +4597,7 @@
   Register scratch1 = scratch0();
   Register scratch2 = ToRegister(instr->temp());
   DwVfpRegister double_scratch = double_scratch0();
-  SwVfpRegister single_scratch = double_scratch.low();
+  DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3());

   ASSERT(!scratch1.is(input_reg) && !scratch1.is(scratch2));
   ASSERT(!scratch2.is(input_reg) && !scratch2.is(scratch1));
@@ -4622,7 +4617,7 @@

   if (instr->truncating()) {
     Register scratch3 = ToRegister(instr->temp2());
-    DwVfpRegister double_scratch2 = ToDoubleRegister(instr->temp3());
+    SwVfpRegister single_scratch = double_scratch.low();
     ASSERT(!scratch3.is(input_reg) &&
            !scratch3.is(scratch1) &&
            !scratch3.is(scratch2));
@@ -4657,14 +4652,12 @@
     __ sub(ip, input_reg, Operand(kHeapObjectTag));
     __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
     __ EmitVFPTruncate(kRoundToZero,
-                       single_scratch,
+                       input_reg,
                        double_scratch,
                        scratch1,
-                       scratch2,
+                       double_scratch2,
                        kCheckForInexactConversion);
     DeoptimizeIf(ne, instr->environment());
-    // Load the result.
-    __ vmov(input_reg, single_scratch);

     if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
       __ cmp(input_reg, Operand(0));
@@ -4728,12 +4721,12 @@
   Register scratch1 = scratch0();
   Register scratch2 = ToRegister(instr->temp());
   DwVfpRegister double_input = ToDoubleRegister(instr->value());
-  SwVfpRegister single_scratch = double_scratch0().low();

   Label done;

   if (instr->truncating()) {
     Register scratch3 = ToRegister(instr->temp2());
+    SwVfpRegister single_scratch = double_scratch0().low();
     __ EmitECMATruncate(result_reg,
                         double_input,
                         single_scratch,
@@ -4741,18 +4734,17 @@
                         scratch2,
                         scratch3);
   } else {
-    VFPRoundingMode rounding_mode = kRoundToMinusInf;
-    __ EmitVFPTruncate(rounding_mode,
-                       single_scratch,
+    DwVfpRegister double_scratch = double_scratch0();
+    __ EmitVFPTruncate(kRoundToMinusInf,
+                       result_reg,
                        double_input,
                        scratch1,
-                       scratch2,
+                       double_scratch,
                        kCheckForInexactConversion);
+
     // Deoptimize if we had a vfp invalid exception,
     // including inexact operation.
     DeoptimizeIf(ne, instr->environment());
-    // Retrieve the result.
-    __ vmov(result_reg, single_scratch);
   }
     __ bind(&done);
 }
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Sep 27 00:45:49 2012 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Oct 8 05:50:15 2012
@@ -2437,16 +2437,27 @@


 void MacroAssembler::EmitVFPTruncate(VFPRoundingMode rounding_mode,
-                                     SwVfpRegister result,
+                                     Register result,
                                      DwVfpRegister double_input,
-                                     Register scratch1,
-                                     Register scratch2,
+                                     Register scratch,
+                                     DwVfpRegister double_scratch,
CheckForInexactConversion check_inexact) {
+  ASSERT(!result.is(scratch));
+  ASSERT(!double_input.is(double_scratch));
+
   ASSERT(CpuFeatures::IsSupported(VFP2));
   CpuFeatures::Scope scope(VFP2);
-  Register prev_fpscr = scratch1;
-  Register scratch = scratch2;
+  Register prev_fpscr = result;
+  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);

+  // Convert to integer, respecting rounding mode.
   int32_t check_inexact_conversion =
(check_inexact == kCheckForInexactConversion) ? kVFPInexactExceptionBit : 0;

@@ -2468,7 +2479,7 @@
   vmsr(scratch);

   // Convert the argument to an integer.
-  vcvt_s32_f64(result,
+  vcvt_s32_f64(double_scratch.low(),
                double_input,
                (rounding_mode == kRoundToZero) ? kDefaultRoundToZero
                                                : kFPSCRRounding);
@@ -2477,8 +2488,12 @@
   vmrs(scratch);
   // Restore FPSCR.
   vmsr(prev_fpscr);
+  // Move the converted value into the result register.
+  vmov(result, double_scratch.low());
   // Check for vfp exceptions.
   tst(scratch, Operand(kVFPExceptionMask | check_inexact_conversion));
+
+  bind(&done);
 }


=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Sep 27 00:45:49 2012 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Oct 8 05:50:15 2012
@@ -939,21 +939,22 @@
                       DwVfpRegister 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.
   // Clears the z flag (ne condition) if an overflow occurs.
- // If exact_conversion is true, the z flag is also cleared if the conversion
-  // was inexact, i.e. if the double value could not be converted exactly
-  // to a 32bit integer.
+ // If kCheckForInexactConversion is passed, the z flag is also cleared if the + // conversion was inexact, i.e. if the double value could not be converted
+  // exactly to a 32-bit integer.
   void EmitVFPTruncate(VFPRoundingMode rounding_mode,
-                       SwVfpRegister result,
+                       Register result,
                        DwVfpRegister double_input,
-                       Register scratch1,
-                       Register scratch2,
+                       Register scratch,
+                       DwVfpRegister double_scratch,
                        CheckForInexactConversion check
                            = kDontCheckForInexactConversion);

   // Helper for EmitECMATruncate.
-  // This will truncate a floating-point value outside of the singed 32bit
+  // This will truncate a floating-point value outside of the signed 32bit
   // integer range to a 32bit signed integer.
   // Expects the double value loaded in input_high and input_low.
   // Exits with the answer in 'result'.
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Sep 27 00:45:49 2012 +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Oct 8 05:50:15 2012
@@ -3646,6 +3646,7 @@
                                 Register scratch0,
                                 Register scratch1,
                                 DwVfpRegister double_scratch0,
+                                DwVfpRegister double_scratch1,
                                 Label* fail) {
   if (CpuFeatures::IsSupported(VFP2)) {
     CpuFeatures::Scope scope(VFP2);
@@ -3662,13 +3663,12 @@
     __ sub(ip, key, Operand(kHeapObjectTag));
     __ vldr(double_scratch0, ip, HeapNumber::kValueOffset);
     __ EmitVFPTruncate(kRoundToZero,
-                       double_scratch0.low(),
+                       scratch0,
                        double_scratch0,
-                       scratch0,
                        scratch1,
+                       double_scratch1,
                        kCheckForInexactConversion);
     __ b(ne, fail);
-    __ vmov(scratch0, double_scratch0.low());
     __ TrySmiTag(scratch0, fail, scratch1);
     __ mov(key, scratch0);
     __ bind(&key_ok);
@@ -3696,7 +3696,7 @@
   // 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, r4, r5, d1, &miss_force_generic);
+  GenerateSmiKeyCheck(masm, key, r4, r5, d1, d2, &miss_force_generic);

   __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
   // r3: elements array
@@ -4030,7 +4030,7 @@
   // 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, r4, r5, d1, &miss_force_generic);
+  GenerateSmiKeyCheck(masm, key, r4, r5, d1, d2, &miss_force_generic);

   __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));

@@ -4365,7 +4365,7 @@
   // 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, r0, r4, r5, d1, &miss_force_generic);
+  GenerateSmiKeyCheck(masm, r0, r4, r5, d1, d2, &miss_force_generic);

   // Get the elements array.
   __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
@@ -4417,7 +4417,7 @@
   // 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, r4, r5, d1, &miss_force_generic);
+  GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, d2, &miss_force_generic);

   // Get the elements array.
   __ ldr(elements_reg,
@@ -4493,7 +4493,7 @@
   // 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, r4, r5, d1, &miss_force_generic);
+  GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, d2, &miss_force_generic);

   if (IsFastSmiElementsKind(elements_kind)) {
     __ JumpIfNotSmi(value_reg, &transition_elements_kind);
@@ -4661,7 +4661,7 @@
   // 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, r4, r5, d1, &miss_force_generic);
+  GenerateSmiKeyCheck(masm, key_reg, r4, r5, d1, d2, &miss_force_generic);

   __ ldr(elements_reg,
          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to