[x64] simply tweak materialization of float/double constants
authorbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 17 Oct 2014 04:18:38 +0000 (04:18 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 17 Oct 2014 04:18:38 +0000 (04:18 +0000)
port 24485
Fixed a bug of "psllq" instruction in x64

R=bmeurer@chromium.org

Review URL: https://codereview.chromium.org/658813003

Patch from Weiliang Lin <weiliang.lin@intel.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24673 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/compiler/x64/code-generator-x64.cc
src/x64/assembler-x64-inl.h
src/x64/assembler-x64.cc
src/x64/assembler-x64.h
src/x64/disasm-x64.cc
src/x64/macro-assembler-x64.cc
src/x64/macro-assembler-x64.h
test/cctest/test-disasm-x64.cc

index b4dfc25f23e5cc7a30f6e02459fc5cb9e798a1a4..070c7bb33b571e7fc48733454b995ba384d19920 100644 (file)
@@ -896,22 +896,22 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
       }
     } else if (src.type() == Constant::kFloat32) {
       // TODO(turbofan): Can we do better here?
-      __ movl(kScratchRegister, Immediate(bit_cast<int32_t>(src.ToFloat32())));
+      uint32_t src_const = bit_cast<uint32_t>(src.ToFloat32());
       if (destination->IsDoubleRegister()) {
-        XMMRegister dst = g.ToDoubleRegister(destination);
-        __ movq(dst, kScratchRegister);
+        __ Move(g.ToDoubleRegister(destination), src_const);
       } else {
         DCHECK(destination->IsDoubleStackSlot());
         Operand dst = g.ToOperand(destination);
-        __ movl(dst, kScratchRegister);
+        __ movl(dst, Immediate(src_const));
       }
     } else {
       DCHECK_EQ(Constant::kFloat64, src.type());
-      __ movq(kScratchRegister, bit_cast<int64_t>(src.ToFloat64()));
+      uint64_t src_const = bit_cast<uint64_t>(src.ToFloat64());
       if (destination->IsDoubleRegister()) {
-        __ movq(g.ToDoubleRegister(destination), kScratchRegister);
+        __ Move(g.ToDoubleRegister(destination), src_const);
       } else {
         DCHECK(destination->IsDoubleStackSlot());
+        __ movq(kScratchRegister, src_const);
         __ movq(g.ToOperand(destination), kScratchRegister);
       }
     }
index b64bbfb664f55797d179ac6e2beab1ce1c33fc74..c3d2cdf2eba0cf8b8a51428497d916f99bb3d4bf 100644 (file)
@@ -179,6 +179,11 @@ void Assembler::emit_optional_rex_32(Register rm_reg) {
 }
 
 
+void Assembler::emit_optional_rex_32(XMMRegister rm_reg) {
+  if (rm_reg.high_bit()) emit(0x41);
+}
+
+
 void Assembler::emit_optional_rex_32(const Operand& op) {
   if (op.rex_ != 0) emit(0x40 | op.rex_);
 }
index 6e44253ed5218d40cd45395fff2ec337380a89ad..7965e771f7d7d5d5c7cd05f9568774cdc727e364 100644 (file)
@@ -2614,6 +2614,7 @@ void Assembler::movss(const Operand& src, XMMRegister dst) {
 void Assembler::psllq(XMMRegister reg, byte imm8) {
   EnsureSpace ensure_space(this);
   emit(0x66);
+  emit_optional_rex_32(reg);
   emit(0x0F);
   emit(0x73);
   emit_sse_operand(rsi, reg);  // rsi == 6
@@ -2621,6 +2622,39 @@ void Assembler::psllq(XMMRegister reg, byte imm8) {
 }
 
 
+void Assembler::psrlq(XMMRegister reg, byte imm8) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(reg);
+  emit(0x0F);
+  emit(0x73);
+  emit_sse_operand(rdx, reg);  // rdx == 2
+  emit(imm8);
+}
+
+
+void Assembler::pslld(XMMRegister reg, byte imm8) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(reg);
+  emit(0x0F);
+  emit(0x72);
+  emit_sse_operand(rsi, reg);  // rsi == 6
+  emit(imm8);
+}
+
+
+void Assembler::psrld(XMMRegister reg, byte imm8) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(reg);
+  emit(0x0F);
+  emit(0x72);
+  emit_sse_operand(rdx, reg);  // rdx == 2
+  emit(imm8);
+}
+
+
 void Assembler::cvttss2si(Register dst, const Operand& src) {
   EnsureSpace ensure_space(this);
   emit(0xF3);
@@ -2966,6 +3000,16 @@ void Assembler::movmskps(Register dst, XMMRegister src) {
 }
 
 
+void Assembler::pcmpeqd(XMMRegister dst, XMMRegister src) {
+  EnsureSpace ensure_space(this);
+  emit(0x66);
+  emit_optional_rex_32(dst, src);
+  emit(0x0F);
+  emit(0x76);
+  emit_sse_operand(dst, src);
+}
+
+
 void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
   Register ireg = { reg.code() };
   emit_operand(ireg, adr);
index aebad60784c708a454c4e90b5cb5be6774cccc48..c0467716fe50ac8ca361100f36846fb68b8356a3 100644 (file)
@@ -1061,6 +1061,9 @@ class Assembler : public AssemblerBase {
   void movapd(XMMRegister dst, XMMRegister src);
 
   void psllq(XMMRegister reg, byte imm8);
+  void psrlq(XMMRegister reg, byte imm8);
+  void pslld(XMMRegister reg, byte imm8);
+  void psrld(XMMRegister reg, byte imm8);
 
   void cvttsd2si(Register dst, const Operand& src);
   void cvttsd2si(Register dst, XMMRegister src);
@@ -1097,6 +1100,7 @@ class Assembler : public AssemblerBase {
   void ucomisd(XMMRegister dst, XMMRegister src);
   void ucomisd(XMMRegister dst, const Operand& src);
   void cmpltsd(XMMRegister dst, XMMRegister src);
+  void pcmpeqd(XMMRegister dst, XMMRegister src);
 
   void movmskpd(Register dst, XMMRegister src);
 
@@ -1271,6 +1275,7 @@ class Assembler : public AssemblerBase {
   // Optionally do as emit_rex_32(Register) if the register number has
   // the high bit set.
   inline void emit_optional_rex_32(Register rm_reg);
+  inline void emit_optional_rex_32(XMMRegister rm_reg);
 
   // Optionally do as emit_rex_32(const Operand&) if the operand register
   // numbers have a high bit set.
index 86e876a3a6d303d59f874bf8e2c735d6c20de1f5..b723f6f6ed1d72531c139127b5dc8df034592796 100644 (file)
@@ -1066,10 +1066,15 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
       } else if (opcode == 0x50) {
         AppendToBuffer("movmskpd %s,", NameOfCPURegister(regop));
         current += PrintRightXMMOperand(current);
+      } else if (opcode == 0x72) {
+        current += 1;
+        AppendToBuffer("%s,%s,%d", (regop == 6) ? "pslld" : "psrld",
+                       NameOfXMMRegister(rm), *current & 0x7f);
+        current += 1;
       } else if (opcode == 0x73) {
         current += 1;
-        DCHECK(regop == 6);
-        AppendToBuffer("psllq,%s,%d", NameOfXMMRegister(rm), *current & 0x7f);
+        AppendToBuffer("%s,%s,%d", (regop == 6) ? "psllq" : "psrlq",
+                       NameOfXMMRegister(rm), *current & 0x7f);
         current += 1;
       } else {
         const char* mnemonic = "?";
index 301afed0091b64bf6e9aea209b18b22ce643011d..7c0a690622d86684a3570f0b08fa631fdc665767 100644 (file)
@@ -2743,6 +2743,57 @@ void MacroAssembler::Move(const Operand& dst, Handle<Object> source) {
 }
 
 
+void MacroAssembler::Move(XMMRegister dst, uint32_t src) {
+  if (src == 0) {
+    xorps(dst, dst);
+  } else {
+    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 {
+      movl(kScratchRegister, Immediate(src));
+      movq(dst, kScratchRegister);
+    }
+  }
+}
+
+
+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 {
+      movq(kScratchRegister, src);
+      movq(dst, kScratchRegister);
+    }
+  }
+}
+
+
 void MacroAssembler::Cmp(Register dst, Handle<Object> source) {
   AllowDeferredHandleDereference smi_check;
   if (source->IsSmi()) {
index 4667be128fccc0a3330ea21d9ebafcd4332d4c08..24eea383949527c3edb7df1e37f34a032884afe3 100644 (file)
@@ -888,6 +888,9 @@ class MacroAssembler: public Assembler {
     movp(dst, reinterpret_cast<void*>(value.location()), rmode);
   }
 
+  void Move(XMMRegister dst, uint32_t src);
+  void Move(XMMRegister dst, uint64_t src);
+
   // Control Flow
   void Jump(Address destination, RelocInfo::Mode rmode);
   void Jump(ExternalReference ext);
index 0c600c2451cb8aa889601e9140bab87feaf0d6ab..004229dd49969f25203bf8cd195ae59b24197262 100644 (file)
@@ -423,6 +423,13 @@ TEST(DisasmX64) {
     __ ucomisd(xmm0, xmm1);
 
     __ andpd(xmm0, xmm1);
+
+    __ pslld(xmm0, 6);
+    __ psrld(xmm0, 6);
+    __ psllq(xmm0, 6);
+    __ psrlq(xmm0, 6);
+
+    __ pcmpeqd(xmm1, xmm0);
   }
 
   // cmov.