Revision: 6269
Author: [email protected]
Date: Tue Jan 11 05:48:49 2011
Log: SSE2 truncating double-to-i.

Review URL: http://codereview.chromium.org/6049008
http://code.google.com/p/v8/source/detail?r=6269

Modified:
 /branches/bleeding_edge/src/assembler.cc
 /branches/bleeding_edge/src/assembler.h
 /branches/bleeding_edge/src/ia32/assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/assembler-ia32.h
 /branches/bleeding_edge/src/ia32/disasm-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/ia32/lithium-ia32.h
 /branches/bleeding_edge/src/serialize.cc
 /branches/bleeding_edge/test/cctest/test-disasm-ia32.cc

=======================================
--- /branches/bleeding_edge/src/assembler.cc    Thu Jan  6 07:53:56 2011
+++ /branches/bleeding_edge/src/assembler.cc    Tue Jan 11 05:48:49 2011
@@ -66,6 +66,7 @@

 const double DoubleConstant::min_int = kMinInt;
 const double DoubleConstant::one_half = 0.5;
+const double DoubleConstant::minus_zero = -0.0;
 const double DoubleConstant::negative_infinity = -V8_INFINITY;


@@ -727,6 +728,12 @@
   return ExternalReference(reinterpret_cast<void*>(
       const_cast<double*>(&DoubleConstant::one_half)));
 }
+
+
+ExternalReference ExternalReference::address_of_minus_zero() {
+  return ExternalReference(reinterpret_cast<void*>(
+      const_cast<double*>(&DoubleConstant::minus_zero)));
+}


 ExternalReference ExternalReference::address_of_negative_infinity() {
=======================================
--- /branches/bleeding_edge/src/assembler.h     Thu Jan  6 07:53:56 2011
+++ /branches/bleeding_edge/src/assembler.h     Tue Jan 11 05:48:49 2011
@@ -50,6 +50,7 @@
  public:
   static const double min_int;
   static const double one_half;
+  static const double minus_zero;
   static const double negative_infinity;
 };

@@ -555,6 +556,7 @@
   // Static variables containing common double constants.
   static ExternalReference address_of_min_int();
   static ExternalReference address_of_one_half();
+  static ExternalReference address_of_minus_zero();
   static ExternalReference address_of_negative_infinity();

   Address address() const {return reinterpret_cast<Address>(address_);}
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.cc Wed Dec 15 08:10:13 2010 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.cc Tue Jan 11 05:48:49 2011
@@ -2463,6 +2463,17 @@
   EMIT(0xEF);
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::por(XMMRegister dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0xEB);
+  emit_sse_operand(dst, src);
+}


 void Assembler::ptest(XMMRegister dst, XMMRegister src) {
@@ -2487,6 +2498,40 @@
   emit_sse_operand(esi, reg);  // esi == 6
   EMIT(shift);
 }
+
+
+void Assembler::psllq(XMMRegister dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0xF3);
+  emit_sse_operand(dst, src);
+}
+
+
+void Assembler::psrlq(XMMRegister reg, int8_t shift) {
+  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0x73);
+  emit_sse_operand(edx, reg);  // edx == 2
+  EMIT(shift);
+}
+
+
+void Assembler::psrlq(XMMRegister dst, XMMRegister src) {
+  ASSERT(CpuFeatures::IsEnabled(SSE2));
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0xD3);
+  emit_sse_operand(dst, src);
+}


 void Assembler::pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle) {
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Wed Dec 15 05:56:41 2010 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Tue Jan 11 05:48:49 2011
@@ -919,9 +919,13 @@

   void pand(XMMRegister dst, XMMRegister src);
   void pxor(XMMRegister dst, XMMRegister src);
+  void por(XMMRegister dst, XMMRegister src);
   void ptest(XMMRegister dst, XMMRegister src);

   void psllq(XMMRegister reg, int8_t shift);
+  void psllq(XMMRegister dst, XMMRegister src);
+  void psrlq(XMMRegister reg, int8_t shift);
+  void psrlq(XMMRegister dst, XMMRegister src);
   void pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle);
   void pextrd(const Operand& dst, XMMRegister src, int8_t offset);

=======================================
--- /branches/bleeding_edge/src/ia32/disasm-ia32.cc     Tue Dec 14 05:21:29 2010
+++ /branches/bleeding_edge/src/ia32/disasm-ia32.cc     Tue Jan 11 05:48:49 2011
@@ -1182,15 +1182,33 @@
                            NameOfXMMRegister(rm),
                            static_cast<int>(imm8));
             data += 2;
+          } else if (*data == 0xF3) {
+            data++;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("psllq %s,%s",
+                           NameOfXMMRegister(regop),
+                           NameOfXMMRegister(rm));
+            data++;
           } else if (*data == 0x73) {
             data++;
             int mod, regop, rm;
             get_modrm(*data, &mod, &regop, &rm);
             int8_t imm8 = static_cast<int8_t>(data[1]);
-            AppendToBuffer("psllq %s,%d",
+            ASSERT(regop == esi || regop == edx);
+            AppendToBuffer("%s %s,%d",
+                           (regop == esi) ? "psllq" : "psrlq",
                            NameOfXMMRegister(rm),
                            static_cast<int>(imm8));
             data += 2;
+          } else if (*data == 0xD3) {
+            data++;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("psrlq %s,%s",
+                           NameOfXMMRegister(regop),
+                           NameOfXMMRegister(rm));
+            data++;
           } else if (*data == 0x7F) {
             AppendToBuffer("movdqa ");
             data++;
@@ -1228,6 +1246,14 @@
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             data++;
+          } else if (*data == 0xEB) {
+            data++;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            AppendToBuffer("por %s,%s",
+                           NameOfXMMRegister(regop),
+                           NameOfXMMRegister(rm));
+            data++;
           } else {
             UnimplementedInstruction();
           }
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jan 11 03:41:01 2011 +++ /branches/bleeding_edge/src/ia32/lithium-codegen-ia32.cc Tue Jan 11 05:48:49 2011
@@ -2971,9 +2971,60 @@
       __ add(Operand(esp), Immediate(kDoubleSize));
       __ bind(&done);
     } else {
-      // This will bail out if the input was not in the int32 range (or,
-      // unfortunately, if the input was 0x80000000).
-      DeoptimizeIf(equal, instr->environment());
+      NearLabel done;
+      Register temp_reg = ToRegister(instr->temporary());
+      XMMRegister xmm_scratch = xmm0;
+
+      // If cvttsd2si succeeded, we're done. Otherwise, we attempt
+      // manual conversion.
+      __ j(not_equal, &done);
+
+      // Get high 32 bits of the input in result_reg and temp_reg.
+      __ pshufd(xmm_scratch, input_reg, 1);
+      __ movd(Operand(temp_reg), xmm_scratch);
+      __ mov(result_reg, temp_reg);
+
+      // Prepare negation mask in temp_reg.
+      __ sar(temp_reg, kBitsPerInt - 1);
+
+      // Extract the exponent from result_reg and subtract adjusted
+      // bias from it. The adjustment is selected in a way such that
+      // when the difference is zero, the answer is in the low 32 bits
+      // of the input, otherwise a shift has to be performed.
+      __ shr(result_reg, HeapNumber::kExponentShift);
+      __ and_(result_reg,
+              HeapNumber::kExponentMask >> HeapNumber::kExponentShift);
+      __ sub(Operand(result_reg),
+             Immediate(HeapNumber::kExponentBias +
+                       HeapNumber::kExponentBits +
+                       HeapNumber::kMantissaBits));
+      // Don't handle big (> kMantissaBits + kExponentBits == 63) or
+      // special exponents.
+      DeoptimizeIf(greater, instr->environment());
+
+      // Zero out the sign and the exponent in the input (by shifting
+      // it to the left) and restore the implicit mantissa bit,
+      // i.e. convert the input to unsigned int64 shifted left by
+      // kExponentBits.
+ ExternalReference minus_zero = ExternalReference::address_of_minus_zero();
+      // Minus zero has the most significant bit set and the other
+      // bits cleared.
+      __ movdbl(xmm_scratch, Operand::StaticVariable(minus_zero));
+      __ psllq(input_reg, HeapNumber::kExponentBits);
+      __ por(input_reg, xmm_scratch);
+
+      // Get the amount to shift the input right in xmm_scratch.
+      __ neg(result_reg);
+      __ movd(xmm_scratch, Operand(result_reg));
+
+      // Shift the input right and extract low 32 bits.
+      __ psrlq(input_reg, xmm_scratch);
+      __ movd(Operand(result_reg), input_reg);
+
+ // Use the prepared mask in temp_reg to negate the result if necessary.
+      __ xor_(result_reg, Operand(temp_reg));
+      __ sub(result_reg, Operand(temp_reg));
+      __ bind(&done);
     }
   } else {
     NearLabel done;
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Jan 11 04:10:11 2011 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Tue Jan 11 05:48:49 2011
@@ -1572,8 +1572,12 @@
       return AssignPointerMap(Define(result, result_temp));
     } else {
       ASSERT(to.IsInteger32());
-      LOperand* value = UseRegister(instr->value());
-      return AssignEnvironment(DefineAsRegister(new LDoubleToI(value)));
+      bool needs_temp = instr->CanTruncateToInt32() &&
+          !CpuFeatures::IsSupported(SSE3);
+      LOperand* value = needs_temp ?
+          UseTempRegister(instr->value()) : UseRegister(instr->value());
+      LOperand* temp = needs_temp ? TempRegister() : NULL;
+ return AssignEnvironment(DefineAsRegister(new LDoubleToI(value, temp)));
     }
   } else if (from.IsInteger32()) {
     if (to.IsTagged()) {
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Jan 11 04:10:11 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h     Tue Jan 11 05:48:49 2011
@@ -1481,12 +1481,17 @@
 // Sometimes truncating conversion from a tagged value to an int32.
 class LDoubleToI: public LUnaryOperation<1> {
  public:
-  explicit LDoubleToI(LOperand* value) : LUnaryOperation<1>(value) { }
+  LDoubleToI(LOperand* value, LOperand* temporary)
+      : LUnaryOperation<1>(value), temporary_(temporary) { }

   DECLARE_CONCRETE_INSTRUCTION(DoubleToI, "double-to-i")
   DECLARE_HYDROGEN_ACCESSOR(Change)

   bool truncating() { return hydrogen()->CanTruncateToInt32(); }
+  LOperand* temporary() const { return temporary_; }
+
+ private:
+  LOperand* temporary_;
 };


=======================================
--- /branches/bleeding_edge/src/serialize.cc    Thu Jan  6 07:53:56 2011
+++ /branches/bleeding_edge/src/serialize.cc    Tue Jan 11 05:48:49 2011
@@ -486,17 +486,21 @@
       UNCLASSIFIED,
       36,
       "LDoubleConstant::one_half");
-  Add(ExternalReference::address_of_negative_infinity().address(),
+  Add(ExternalReference::address_of_minus_zero().address(),
       UNCLASSIFIED,
       37,
+      "LDoubleConstant::minus_zero");
+  Add(ExternalReference::address_of_negative_infinity().address(),
+      UNCLASSIFIED,
+      38,
       "LDoubleConstant::negative_infinity");
   Add(ExternalReference::power_double_double_function().address(),
       UNCLASSIFIED,
-      38,
+      39,
       "power_double_double_function");
   Add(ExternalReference::power_double_int_function().address(),
       UNCLASSIFIED,
-      39,
+      40,
       "power_double_int_function");
   Add(ExternalReference::arguments_marker_location().address(),
       UNCLASSIFIED,
=======================================
--- /branches/bleeding_edge/test/cctest/test-disasm-ia32.cc Mon Jan 3 01:32:42 2011 +++ /branches/bleeding_edge/test/cctest/test-disasm-ia32.cc Tue Jan 11 05:48:49 2011
@@ -416,7 +416,7 @@
     }
   }

-  // andpd, cmpltsd, movaps, psllq.
+  // andpd, cmpltsd, movaps, psllq, psrlq, por.
   {
     if (CpuFeatures::IsSupported(SSE2)) {
       CpuFeatures::Scope fscope(SSE2);
@@ -431,6 +431,18 @@

       __ psllq(xmm0, 17);
       __ psllq(xmm1, 42);
+
+      __ psllq(xmm0, xmm1);
+      __ psllq(xmm1, xmm2);
+
+      __ psrlq(xmm0, 17);
+      __ psrlq(xmm1, 42);
+
+      __ psrlq(xmm0, xmm1);
+      __ psrlq(xmm1, xmm2);
+
+      __ por(xmm0, xmm1);
+      __ por(xmm1, xmm2);
     }
   }

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

Reply via email to