Revision: 24485
Author:   bmeu...@chromium.org
Date:     Thu Oct  9 09:32:59 2014 UTC
Log: [ia32] Better code generation for materialization of float/double constants.

TEST=cctest,mjsunit
R=mstarzin...@chromium.org, ja...@chromium.org

Review URL: https://codereview.chromium.org/645493002
https://code.google.com/p/v8/source/detail?r=24485

Modified:
 /branches/bleeding_edge/src/compiler/ia32/code-generator-ia32.cc
 /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/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h

=======================================
--- /branches/bleeding_edge/src/compiler/ia32/code-generator-ia32.cc Wed Oct 8 10:44:45 2014 UTC +++ /branches/bleeding_edge/src/compiler/ia32/code-generator-ia32.cc Thu Oct 9 09:32:59 2014 UTC
@@ -905,26 +905,23 @@
       __ mov(dst, g.ToImmediate(source));
     } else if (src_constant.type() == Constant::kFloat32) {
       // TODO(turbofan): Can we do better here?
-      Immediate src(bit_cast<int32_t>(src_constant.ToFloat32()));
+      uint32_t src = bit_cast<uint32_t>(src_constant.ToFloat32());
       if (destination->IsDoubleRegister()) {
         XMMRegister dst = g.ToDoubleRegister(destination);
-        __ push(Immediate(src));
-        __ movss(dst, Operand(esp, 0));
-        __ add(esp, Immediate(kDoubleSize / 2));
+        __ Move(dst, src);
       } else {
         DCHECK(destination->IsDoubleStackSlot());
         Operand dst = g.ToOperand(destination);
-        __ mov(dst, src);
+        __ mov(dst, Immediate(src));
       }
     } else {
       DCHECK_EQ(Constant::kFloat64, src_constant.type());
-      double v = src_constant.ToFloat64();
-      uint64_t int_val = bit_cast<uint64_t, double>(v);
-      int32_t lower = static_cast<int32_t>(int_val);
-      int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
+      uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
+      uint32_t lower = static_cast<uint32_t>(src);
+      uint32_t upper = static_cast<uint32_t>(src >> 32);
       if (destination->IsDoubleRegister()) {
         XMMRegister dst = g.ToDoubleRegister(destination);
-        __ Move(dst, v);
+        __ Move(dst, src);
       } else {
         DCHECK(destination->IsDoubleStackSlot());
         Operand dst0 = g.ToOperand(destination);
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.cc Thu Oct 2 09:04:04 2014 UTC +++ /branches/bleeding_edge/src/ia32/assembler-ia32.cc Thu Oct 9 09:32:59 2014 UTC
@@ -2379,6 +2379,26 @@
   EMIT(0x17);
   emit_sse_operand(dst, src);
 }
+
+
+void Assembler::pslld(XMMRegister reg, int8_t shift) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0x72);
+  emit_sse_operand(esi, reg);  // esi == 6
+  EMIT(shift);
+}
+
+
+void Assembler::psrld(XMMRegister reg, int8_t shift) {
+  EnsureSpace ensure_space(this);
+  EMIT(0x66);
+  EMIT(0x0F);
+  EMIT(0x72);
+  emit_sse_operand(edx, reg);  // edx == 2
+  EMIT(shift);
+}


 void Assembler::psllq(XMMRegister reg, int8_t shift) {
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Oct 2 09:04:04 2014 UTC +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Oct 9 09:32:59 2014 UTC
@@ -1024,6 +1024,8 @@
   void por(XMMRegister dst, XMMRegister src);
   void ptest(XMMRegister dst, XMMRegister src);

+  void pslld(XMMRegister reg, int8_t shift);
+  void psrld(XMMRegister reg, int8_t shift);
   void psllq(XMMRegister reg, int8_t shift);
   void psllq(XMMRegister dst, XMMRegister src);
   void psrlq(XMMRegister reg, int8_t shift);
=======================================
--- /branches/bleeding_edge/src/ia32/disasm-ia32.cc Wed Aug 6 08:19:36 2014 UTC +++ /branches/bleeding_edge/src/ia32/disasm-ia32.cc Thu Oct 9 09:32:59 2014 UTC
@@ -1386,6 +1386,15 @@
                            NameOfXMMRegister(regop),
                            NameOfXMMRegister(rm));
             data++;
+          } else if (*data == 0x72) {
+            data++;
+            int mod, regop, rm;
+            get_modrm(*data, &mod, &regop, &rm);
+            int8_t imm8 = static_cast<int8_t>(data[1]);
+            DCHECK(regop == esi || regop == edx);
+            AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld",
+                           NameOfXMMRegister(rm), static_cast<int>(imm8));
+            data += 2;
           } else if (*data == 0x73) {
             data++;
             int mod, regop, rm;
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Sep 30 10:24:11 2014 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Thu Oct 9 09:32:59 2014 UTC
@@ -2616,18 +2616,66 @@
 }


-void MacroAssembler::Move(XMMRegister dst, double val) {
-  // TODO(titzer): recognize double constants with ExternalReferences.
-  uint64_t int_val = bit_cast<uint64_t, double>(val);
-  if (int_val == 0) {
-    xorps(dst, dst);
+void MacroAssembler::Move(XMMRegister dst, uint32_t src) {
+  if (src == 0) {
+    pxor(dst, dst);
   } else {
-    int32_t lower = static_cast<int32_t>(int_val);
-    int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
-    push(Immediate(upper));
-    push(Immediate(lower));
-    movsd(dst, Operand(esp, 0));
-    add(esp, Immediate(kDoubleSize));
+    unsigned cnt = base::bits::CountPopulation32(src);
+    unsigned nlz = base::bits::CountLeadingZeros32(src);
+    unsigned ntz = base::bits::CountTrailingZeros32(src);
+    if (nlz + cnt + ntz == 32) {
+      pcmpeqd(dst, dst);
+      if (ntz == 0) {
+        psrld(dst, 32 - cnt);
+      } else {
+        pslld(dst, 32 - cnt);
+        if (nlz != 0) psrld(dst, nlz);
+      }
+    } else {
+      push(eax);
+      mov(eax, Immediate(src));
+      movd(dst, Operand(eax));
+      pop(eax);
+    }
+  }
+}
+
+
+void MacroAssembler::Move(XMMRegister dst, uint64_t src) {
+  uint32_t lower = static_cast<uint32_t>(src);
+  uint32_t upper = static_cast<uint32_t>(src >> 32);
+  if (upper == 0) {
+    Move(dst, lower);
+  } else {
+    unsigned cnt = base::bits::CountPopulation64(src);
+    unsigned nlz = base::bits::CountLeadingZeros64(src);
+    unsigned ntz = base::bits::CountTrailingZeros64(src);
+    if (nlz + cnt + ntz == 64) {
+      pcmpeqd(dst, dst);
+      if (ntz == 0) {
+        psrlq(dst, 64 - cnt);
+      } else {
+        psllq(dst, 64 - cnt);
+        if (nlz != 0) psrlq(dst, nlz);
+      }
+    } else if (lower == 0) {
+      Move(dst, upper);
+      psllq(dst, 32);
+    } else {
+      push(eax);
+      Move(eax, Immediate(lower));
+      movd(dst, Operand(eax));
+      Move(eax, Immediate(upper));
+      if (CpuFeatures::IsSupported(SSE4_1)) {
+        CpuFeatureScope scope(this, SSE4_1);
+        pinsrd(dst, Operand(eax), 1);
+      } else {
+        psllq(dst, 32);
+        movd(xmm0, Operand(eax));
+        orpd(dst, xmm0);
+      }
+      pop(eax);
+    }
   }
 }

=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Tue Sep 30 10:24:11 2014 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Thu Oct 9 09:32:59 2014 UTC
@@ -842,7 +842,9 @@
   void Move(const Operand& dst, const Immediate& x);

   // Move an immediate into an XMM register.
-  void Move(XMMRegister dst, double val);
+  void Move(XMMRegister dst, uint32_t src);
+  void Move(XMMRegister dst, uint64_t src);
+ void Move(XMMRegister dst, double src) { Move(dst, bit_cast<uint64_t>(src)); }

   // Push a handle value.
   void Push(Handle<Object> handle) { push(Immediate(handle)); }

--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to