[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
This commit is contained in:
bmeurer@chromium.org 2014-10-09 09:32:59 +00:00
parent d50ba88bfd
commit d143beb658
6 changed files with 100 additions and 22 deletions

View File

@ -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<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);

View File

@ -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);

View File

@ -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);

View File

@ -1386,6 +1386,15 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
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;

View File

@ -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<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);
}
}
}

View File

@ -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<uint64_t>(src)); }
// Push a handle value.
void Push(Handle<Object> handle) { push(Immediate(handle)); }