From 0854ee289babbf63bf90b2cf463e2b23697c4a05 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Fri, 17 Oct 2014 04:18:38 +0000 Subject: [PATCH] [x64] simply tweak materialization of float/double constants 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 . git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24673 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/x64/code-generator-x64.cc | 12 ++++---- src/x64/assembler-x64-inl.h | 5 ++++ src/x64/assembler-x64.cc | 44 +++++++++++++++++++++++++++++ src/x64/assembler-x64.h | 5 ++++ src/x64/disasm-x64.cc | 9 ++++-- src/x64/macro-assembler-x64.cc | 51 ++++++++++++++++++++++++++++++++++ src/x64/macro-assembler-x64.h | 3 ++ test/cctest/test-disasm-x64.cc | 7 +++++ 8 files changed, 128 insertions(+), 8 deletions(-) diff --git a/src/compiler/x64/code-generator-x64.cc b/src/compiler/x64/code-generator-x64.cc index b4dfc25..070c7bb 100644 --- a/src/compiler/x64/code-generator-x64.cc +++ b/src/compiler/x64/code-generator-x64.cc @@ -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(src.ToFloat32()))); + uint32_t src_const = bit_cast(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(src.ToFloat64())); + uint64_t src_const = bit_cast(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); } } diff --git a/src/x64/assembler-x64-inl.h b/src/x64/assembler-x64-inl.h index b64bbfb..c3d2cdf 100644 --- a/src/x64/assembler-x64-inl.h +++ b/src/x64/assembler-x64-inl.h @@ -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_); } diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 6e44253..7965e77 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -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); diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index aebad60..c046771 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -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. diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc index 86e876a..b723f6f 100644 --- a/src/x64/disasm-x64.cc +++ b/src/x64/disasm-x64.cc @@ -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 = "?"; diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 301afed..7c0a690 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -2743,6 +2743,57 @@ void MacroAssembler::Move(const Operand& dst, Handle 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(src); + uint32_t upper = static_cast(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 source) { AllowDeferredHandleDereference smi_check; if (source->IsSmi()) { diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index 4667be1..24eea38 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -888,6 +888,9 @@ class MacroAssembler: public Assembler { movp(dst, reinterpret_cast(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); diff --git a/test/cctest/test-disasm-x64.cc b/test/cctest/test-disasm-x64.cc index 0c600c2..004229d 100644 --- a/test/cctest/test-disasm-x64.cc +++ b/test/cctest/test-disasm-x64.cc @@ -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. -- 2.7.4