From d143beb658c31efc5e05a4691eca0266b0553269 Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Thu, 9 Oct 2014 09:32:59 +0000 Subject: [PATCH] [ia32] Better code generation for materialization of float/double constants. TEST=cctest,mjsunit R=mstarzinger@chromium.org, jarin@chromium.org Review URL: https://codereview.chromium.org/645493002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24485 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/ia32/code-generator-ia32.cc | 17 +++--- src/ia32/assembler-ia32.cc | 20 +++++++ src/ia32/assembler-ia32.h | 2 + src/ia32/disasm-ia32.cc | 9 +++ src/ia32/macro-assembler-ia32.cc | 70 ++++++++++++++++++++---- src/ia32/macro-assembler-ia32.h | 4 +- 6 files changed, 100 insertions(+), 22 deletions(-) diff --git a/src/compiler/ia32/code-generator-ia32.cc b/src/compiler/ia32/code-generator-ia32.cc index 945e99d092..84933de2cd 100644 --- a/src/compiler/ia32/code-generator-ia32.cc +++ b/src/compiler/ia32/code-generator-ia32.cc @@ -905,26 +905,23 @@ void CodeGenerator::AssembleMove(InstructionOperand* source, __ mov(dst, g.ToImmediate(source)); } else if (src_constant.type() == Constant::kFloat32) { // TODO(turbofan): Can we do better here? - Immediate src(bit_cast(src_constant.ToFloat32())); + uint32_t src = bit_cast(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(v); - int32_t lower = static_cast(int_val); - int32_t upper = static_cast(int_val >> kBitsPerInt); + uint64_t src = bit_cast(src_constant.ToFloat64()); + uint32_t lower = static_cast(src); + uint32_t upper = static_cast(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); diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc index 5e8333d11a..7a9b963488 100644 --- a/src/ia32/assembler-ia32.cc +++ b/src/ia32/assembler-ia32.cc @@ -2381,6 +2381,26 @@ void Assembler::ptest(XMMRegister dst, XMMRegister 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) { EnsureSpace ensure_space(this); EMIT(0x66); diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h index 4532a67065..3cab0e444d 100644 --- a/src/ia32/assembler-ia32.h +++ b/src/ia32/assembler-ia32.h @@ -1024,6 +1024,8 @@ class Assembler : public AssemblerBase { 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); diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc index 22c2a55c17..04279d08bf 100644 --- a/src/ia32/disasm-ia32.cc +++ b/src/ia32/disasm-ia32.cc @@ -1386,6 +1386,15 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector out_buffer, NameOfXMMRegister(regop), NameOfXMMRegister(rm)); data++; + } else if (*data == 0x72) { + data++; + int mod, regop, rm; + get_modrm(*data, &mod, ®op, &rm); + int8_t imm8 = static_cast(data[1]); + DCHECK(regop == esi || regop == edx); + AppendToBuffer("%s %s,%d", (regop == esi) ? "pslld" : "psrld", + NameOfXMMRegister(rm), static_cast(imm8)); + data += 2; } else if (*data == 0x73) { data++; int mod, regop, rm; diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 43043e5b27..8616848e8a 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -2616,18 +2616,66 @@ void MacroAssembler::Move(const Operand& dst, const Immediate& x) { } -void MacroAssembler::Move(XMMRegister dst, double val) { - // TODO(titzer): recognize double constants with ExternalReferences. - uint64_t int_val = bit_cast(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(int_val); - int32_t upper = static_cast(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(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 { + 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); + } } } diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index b11145db0f..597dd21309 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -842,7 +842,9 @@ class MacroAssembler: public Assembler { 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(src)); } // Push a handle value. void Push(Handle handle) { push(Immediate(handle)); }