Bug 676287 - IonMonkey: inline some constant doubles in code. r=dvander

This commit is contained in:
Tom Schuster 2012-06-24 15:28:50 +02:00
parent 049f589808
commit 9e785e924d
7 changed files with 117 additions and 10 deletions

View File

@ -287,6 +287,7 @@ private:
OP2_XORPD_VpdWpd = 0x57,
OP2_MOVD_VdEd = 0x6E,
OP2_PSRLDQ_Vd = 0x73,
OP2_PCMPEQW = 0x75,
OP2_MOVD_EdVd = 0x7E,
OP2_JCC_rel32 = 0x80,
OP_SETCC = 0x90,
@ -675,7 +676,7 @@ public:
void fstp_m(int offset, RegisterID base)
{
m_formatter.oneByteOp(OP_FPU6, FPU6_OP_FSTP, base, offset);
m_formatter.oneByteOp(OP_FPU6, FPU6_OP_FSTP, base, offset);
}
void negl_r(RegisterID dst)
@ -2049,6 +2050,15 @@ public:
// SSE operations:
void pcmpeqw_rr(XMMRegisterID src, XMMRegisterID dst)
{
js::JaegerSpew(js::JSpew_Insns,
IPFX "pcmpeqw %s, %s\n", MAYBE_PAD,
nameFPReg(src), nameFPReg(dst));
m_formatter.prefix(PRE_SSE_66);
m_formatter.twoByteOp(OP2_PCMPEQW, (RegisterID)dst, (RegisterID)src); /* right order ? */
}
void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
{
js::JaegerSpew(js::JSpew_Insns,
@ -2185,13 +2195,33 @@ public:
void psrldq_rr(XMMRegisterID dest, int shift)
{
js::JaegerSpew(js::JSpew_Insns,
IPFX "pslldq %s, %d\n", MAYBE_PAD,
IPFX "psrldq %s, %d\n", MAYBE_PAD,
nameFPReg(dest), shift);
m_formatter.prefix(PRE_SSE_66);
m_formatter.twoByteOp(OP2_PSRLDQ_Vd, (RegisterID)3, (RegisterID)dest);
m_formatter.immediate8(shift);
}
void psllq_rr(XMMRegisterID dest, int shift)
{
js::JaegerSpew(js::JSpew_Insns,
IPFX "psllq %s, %d\n", MAYBE_PAD,
nameFPReg(dest), shift);
m_formatter.prefix(PRE_SSE_66);
m_formatter.twoByteOp(OP2_PSRLDQ_Vd, (RegisterID)6, (RegisterID)dest);
m_formatter.immediate8(shift);
}
void psrlq_rr(XMMRegisterID dest, int shift)
{
js::JaegerSpew(js::JSpew_Insns,
IPFX "psrlq %s, %d\n", MAYBE_PAD,
nameFPReg(dest), shift);
m_formatter.prefix(PRE_SSE_66);
m_formatter.twoByteOp(OP2_PSRLDQ_Vd, (RegisterID)2, (RegisterID)dest);
m_formatter.immediate8(shift);
}
void movmskpd_rr(XMMRegisterID src, RegisterID dst)
{
js::JaegerSpew(js::JSpew_Insns,

View File

@ -1007,9 +1007,15 @@ class AssemblerX86Shared
JS_NOT_REACHED("unexpected operand kind");
}
}
void psrlq(Imm32 shift, const FloatRegister &dest) {
void psrldq(Imm32 shift, const FloatRegister &dest) {
masm.psrldq_rr(dest.code(), shift.value);
}
void psllq(Imm32 shift, const FloatRegister &dest) {
masm.psllq_rr(dest.code(), shift.value);
}
void psrlq(Imm32 shift, const FloatRegister &dest) {
masm.psrlq_rr(dest.code(), shift.value);
}
void cvtsi2sd(const Operand &src, const FloatRegister &dest) {
switch (src.kind()) {
@ -1042,6 +1048,9 @@ class AssemblerX86Shared
void ucomisd(const FloatRegister &lhs, const FloatRegister &rhs) {
masm.ucomisd_rr(rhs.code(), lhs.code());
}
void pcmpeqw(const FloatRegister &lhs, const FloatRegister &rhs) {
masm.pcmpeqw_rr(rhs.code(), lhs.code());
}
void movd(const Register &src, const FloatRegister &dest) {
masm.movd_rr(src.code(), dest.code());
}

View File

@ -323,6 +323,43 @@ class MacroAssemblerX86Shared : public Assembler
bind(&done);
}
bool maybeInlineDouble(uint64_t u, const FloatRegister &dest) {
// This implements parts of "13.4 Generating constants" of
// "2. Optimizing subroutines in assembly language" by Agner Fog.
switch (u) {
case 0:
xorpd(dest, dest);
break;
case 0x3fe0000000000000: // 0.5
pcmpeqw(dest, dest);
psllq(Imm32(55), dest);
psrlq(Imm32(2), dest);
break;
case 0x3ff0000000000000: // 1.0
pcmpeqw(dest, dest);
psllq(Imm32(54), dest);
psrlq(Imm32(2), dest);
break;
case 0x3ff8000000000000: // 1.5
pcmpeqw(dest, dest);
psllq(Imm32(53), dest);
psrlq(Imm32(2), dest);
break;
case 0x4000000000000000: // 2.0
pcmpeqw(dest, dest);
psllq(Imm32(63), dest);
psrlq(Imm32(1), dest);
break;
case 0xc000000000000000: // -2.0
pcmpeqw(dest, dest);
psllq(Imm32(62), dest);
break;
default:
return false;
}
return true;
}
// Emit a JMP that can be toggled to a CMP. See ToggleToJmp(), ToggleToCmp().
CodeOffsetLabel toggledJump(Label *label) {
CodeOffsetLabel offset(size());

View File

@ -704,9 +704,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
double d;
} pun;
pun.d = d;
if (pun.u == 0) {
xorpd(dest, dest);
} else {
if (!maybeInlineDouble(pun.u, dest)) {
movq(ImmWord(pun.u), ScratchReg);
movqsd(ScratchReg, dest);
}

View File

@ -199,10 +199,8 @@ CodeGeneratorX86::visitDouble(LDouble *ins)
} dpun;
dpun.d = v.toDouble();
if (dpun.u == 0) {
masm.xorpd(ToFloatRegister(out), ToFloatRegister(out));
if (masm.maybeInlineDouble(dpun.u, ToFloatRegister(out)))
return true;
}
DeferredDouble *d = new DeferredDouble(cindex->index());
if (!deferredDoubles_.append(d))

View File

@ -542,7 +542,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
// Note: this function clobbers the source register.
void boxDouble(const FloatRegister &src, const ValueOperand &dest) {
movd(src, dest.payloadReg());
psrlq(Imm32(4), src);
psrldq(Imm32(4), src);
movd(src, dest.typeReg());
}
void unboxInt32(const ValueOperand &src, const Register &dest) {

View File

@ -0,0 +1,35 @@
function add0_5 (n) {
return n + 0.5;
}
function add1_0 (n) {
return n + 1;
}
function add1_5 (n) {
return n + 1.5;
}
function add2_0 (n) {
return n + 2;
}
function sub2_0 (n) {
return n - 2;
}
var num = 1.5;
function main () {
for (var i = 0; i < 10000; i++) {
assertEq(add0_5(num), 2);
assertEq(add1_0(num), 2.5);
assertEq(add1_5(num), 3);
assertEq(add2_0(num), 3.5);
assertEq(sub2_0(num), -0.5);
}
}
for (var i = 0; i < 1000; i++)
main();