[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:
parent
d50ba88bfd
commit
d143beb658
@ -905,26 +905,23 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
|||||||
__ mov(dst, g.ToImmediate(source));
|
__ mov(dst, g.ToImmediate(source));
|
||||||
} else if (src_constant.type() == Constant::kFloat32) {
|
} else if (src_constant.type() == Constant::kFloat32) {
|
||||||
// TODO(turbofan): Can we do better here?
|
// 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()) {
|
if (destination->IsDoubleRegister()) {
|
||||||
XMMRegister dst = g.ToDoubleRegister(destination);
|
XMMRegister dst = g.ToDoubleRegister(destination);
|
||||||
__ push(Immediate(src));
|
__ Move(dst, src);
|
||||||
__ movss(dst, Operand(esp, 0));
|
|
||||||
__ add(esp, Immediate(kDoubleSize / 2));
|
|
||||||
} else {
|
} else {
|
||||||
DCHECK(destination->IsDoubleStackSlot());
|
DCHECK(destination->IsDoubleStackSlot());
|
||||||
Operand dst = g.ToOperand(destination);
|
Operand dst = g.ToOperand(destination);
|
||||||
__ mov(dst, src);
|
__ mov(dst, Immediate(src));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DCHECK_EQ(Constant::kFloat64, src_constant.type());
|
DCHECK_EQ(Constant::kFloat64, src_constant.type());
|
||||||
double v = src_constant.ToFloat64();
|
uint64_t src = bit_cast<uint64_t>(src_constant.ToFloat64());
|
||||||
uint64_t int_val = bit_cast<uint64_t, double>(v);
|
uint32_t lower = static_cast<uint32_t>(src);
|
||||||
int32_t lower = static_cast<int32_t>(int_val);
|
uint32_t upper = static_cast<uint32_t>(src >> 32);
|
||||||
int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
|
|
||||||
if (destination->IsDoubleRegister()) {
|
if (destination->IsDoubleRegister()) {
|
||||||
XMMRegister dst = g.ToDoubleRegister(destination);
|
XMMRegister dst = g.ToDoubleRegister(destination);
|
||||||
__ Move(dst, v);
|
__ Move(dst, src);
|
||||||
} else {
|
} else {
|
||||||
DCHECK(destination->IsDoubleStackSlot());
|
DCHECK(destination->IsDoubleStackSlot());
|
||||||
Operand dst0 = g.ToOperand(destination);
|
Operand dst0 = g.ToOperand(destination);
|
||||||
|
@ -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) {
|
void Assembler::psllq(XMMRegister reg, int8_t shift) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
EMIT(0x66);
|
EMIT(0x66);
|
||||||
|
@ -1024,6 +1024,8 @@ class Assembler : public AssemblerBase {
|
|||||||
void por(XMMRegister dst, XMMRegister src);
|
void por(XMMRegister dst, XMMRegister src);
|
||||||
void ptest(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 reg, int8_t shift);
|
||||||
void psllq(XMMRegister dst, XMMRegister src);
|
void psllq(XMMRegister dst, XMMRegister src);
|
||||||
void psrlq(XMMRegister reg, int8_t shift);
|
void psrlq(XMMRegister reg, int8_t shift);
|
||||||
|
@ -1386,6 +1386,15 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
|
|||||||
NameOfXMMRegister(regop),
|
NameOfXMMRegister(regop),
|
||||||
NameOfXMMRegister(rm));
|
NameOfXMMRegister(rm));
|
||||||
data++;
|
data++;
|
||||||
|
} else if (*data == 0x72) {
|
||||||
|
data++;
|
||||||
|
int mod, regop, rm;
|
||||||
|
get_modrm(*data, &mod, ®op, &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) {
|
} else if (*data == 0x73) {
|
||||||
data++;
|
data++;
|
||||||
int mod, regop, rm;
|
int mod, regop, rm;
|
||||||
|
@ -2616,18 +2616,66 @@ void MacroAssembler::Move(const Operand& dst, const Immediate& x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::Move(XMMRegister dst, double val) {
|
void MacroAssembler::Move(XMMRegister dst, uint32_t src) {
|
||||||
// TODO(titzer): recognize double constants with ExternalReferences.
|
if (src == 0) {
|
||||||
uint64_t int_val = bit_cast<uint64_t, double>(val);
|
pxor(dst, dst);
|
||||||
if (int_val == 0) {
|
|
||||||
xorps(dst, dst);
|
|
||||||
} else {
|
} else {
|
||||||
int32_t lower = static_cast<int32_t>(int_val);
|
unsigned cnt = base::bits::CountPopulation32(src);
|
||||||
int32_t upper = static_cast<int32_t>(int_val >> kBitsPerInt);
|
unsigned nlz = base::bits::CountLeadingZeros32(src);
|
||||||
push(Immediate(upper));
|
unsigned ntz = base::bits::CountTrailingZeros32(src);
|
||||||
push(Immediate(lower));
|
if (nlz + cnt + ntz == 32) {
|
||||||
movsd(dst, Operand(esp, 0));
|
pcmpeqd(dst, dst);
|
||||||
add(esp, Immediate(kDoubleSize));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,7 +842,9 @@ class MacroAssembler: public Assembler {
|
|||||||
void Move(const Operand& dst, const Immediate& x);
|
void Move(const Operand& dst, const Immediate& x);
|
||||||
|
|
||||||
// Move an immediate into an XMM register.
|
// 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.
|
// Push a handle value.
|
||||||
void Push(Handle<Object> handle) { push(Immediate(handle)); }
|
void Push(Handle<Object> handle) { push(Immediate(handle)); }
|
||||||
|
Loading…
Reference in New Issue
Block a user