Bug 1232205 - Wasm baseline: Factor out floating min and max, on x86-shared. r=bbouvier

--HG--
extra : rebase_source : d6a672b57f12fc7c848cdd040bb4129c23ee3cb9
This commit is contained in:
Lars T Hansen 2016-06-02 16:54:09 +02:00
Родитель 5f37b82773
Коммит 8ec23c07dd
3 изменённых файлов: 99 добавлений и 76 удалений

Просмотреть файл

@ -663,45 +663,10 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD* ins)
MOZ_ASSERT(first == output);
#endif
Label done, nan, minMaxInst;
bool specialHandling = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
bool isMax = ins->mir()->isMax();
// Do a vucomisd to catch equality and NaNs, which both require special
// handling. If the operands are ordered and inequal, we branch straight to
// the min/max instruction. If we wanted, we could also branch for less-than
// or greater-than here instead of using min/max, however these conditions
// will sometimes be hard on the branch predictor.
masm.vucomisd(second, first);
masm.j(Assembler::NotEqual, &minMaxInst);
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN())
masm.j(Assembler::Parity, &nan);
// Ordered and equal. The operands are bit-identical unless they are zero
// and negative zero. These instructions merge the sign bits in that
// case, and are no-ops otherwise.
if (ins->mir()->isMax())
masm.vandpd(second, first, first);
else
masm.vorpd(second, first, first);
masm.jump(&done);
// x86's min/max are not symmetric; if either operand is a NaN, they return
// the read-only operand. We need to return a NaN if either operand is a
// NaN, so we explicitly check for a NaN in the read-write operand.
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN()) {
masm.bind(&nan);
masm.vucomisd(first, first);
masm.j(Assembler::Parity, &done);
}
// When the values are inequal, or second is NaN, x86's min and max will
// return the value we need.
masm.bind(&minMaxInst);
if (ins->mir()->isMax())
masm.vmaxsd(second, first, first);
else
masm.vminsd(second, first, first);
masm.bind(&done);
masm.minMaxDouble(first, second, specialHandling, isMax);
}
void
@ -714,45 +679,10 @@ CodeGeneratorX86Shared::visitMinMaxF(LMinMaxF* ins)
MOZ_ASSERT(first == output);
#endif
Label done, nan, minMaxInst;
bool specialHandling = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
bool isMax = ins->mir()->isMax();
// Do a vucomiss to catch equality and NaNs, which both require special
// handling. If the operands are ordered and inequal, we branch straight to
// the min/max instruction. If we wanted, we could also branch for less-than
// or greater-than here instead of using min/max, however these conditions
// will sometimes be hard on the branch predictor.
masm.vucomiss(second, first);
masm.j(Assembler::NotEqual, &minMaxInst);
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN())
masm.j(Assembler::Parity, &nan);
// Ordered and equal. The operands are bit-identical unless they are zero
// and negative zero. These instructions merge the sign bits in that
// case, and are no-ops otherwise.
if (ins->mir()->isMax())
masm.vandps(second, first, first);
else
masm.vorps(second, first, first);
masm.jump(&done);
// x86's min/max are not symmetric; if either operand is a NaN, they return
// the read-only operand. We need to return a NaN if either operand is a
// NaN, so we explicitly check for a NaN in the read-write operand.
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN()) {
masm.bind(&nan);
masm.vucomiss(first, first);
masm.j(Assembler::Parity, &done);
}
// When the values are inequal, or second is NaN, x86's min and max will
// return the value we need.
masm.bind(&minMaxInst);
if (ins->mir()->isMax())
masm.vmaxss(second, first, first);
else
masm.vminss(second, first, first);
masm.bind(&done);
masm.minMaxFloat32(first, second, specialHandling, isMax);
}
void

Просмотреть файл

@ -315,6 +315,94 @@ MacroAssemblerX86Shared::asmMergeWith(const MacroAssemblerX86Shared& other)
return true;
}
void
MacroAssemblerX86Shared::minMaxDouble(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax)
{
Label done, nan, minMaxInst;
// Do a vucomisd to catch equality and NaNs, which both require special
// handling. If the operands are ordered and inequal, we branch straight to
// the min/max instruction. If we wanted, we could also branch for less-than
// or greater-than here instead of using min/max, however these conditions
// will sometimes be hard on the branch predictor.
vucomisd(second, first);
j(Assembler::NotEqual, &minMaxInst);
if (handleNaN)
j(Assembler::Parity, &nan);
// Ordered and equal. The operands are bit-identical unless they are zero
// and negative zero. These instructions merge the sign bits in that
// case, and are no-ops otherwise.
if (isMax)
vandpd(second, first, first);
else
vorpd(second, first, first);
jump(&done);
// x86's min/max are not symmetric; if either operand is a NaN, they return
// the read-only operand. We need to return a NaN if either operand is a
// NaN, so we explicitly check for a NaN in the read-write operand.
if (handleNaN) {
bind(&nan);
vucomisd(first, first);
j(Assembler::Parity, &done);
}
// When the values are inequal, or second is NaN, x86's min and max will
// return the value we need.
bind(&minMaxInst);
if (isMax)
vmaxsd(second, first, first);
else
vminsd(second, first, first);
bind(&done);
}
void
MacroAssemblerX86Shared::minMaxFloat32(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax)
{
Label done, nan, minMaxInst;
// Do a vucomiss to catch equality and NaNs, which both require special
// handling. If the operands are ordered and inequal, we branch straight to
// the min/max instruction. If we wanted, we could also branch for less-than
// or greater-than here instead of using min/max, however these conditions
// will sometimes be hard on the branch predictor.
vucomiss(second, first);
j(Assembler::NotEqual, &minMaxInst);
if (handleNaN)
j(Assembler::Parity, &nan);
// Ordered and equal. The operands are bit-identical unless they are zero
// and negative zero. These instructions merge the sign bits in that
// case, and are no-ops otherwise.
if (isMax)
vandps(second, first, first);
else
vorps(second, first, first);
jump(&done);
// x86's min/max are not symmetric; if either operand is a NaN, they return
// the read-only operand. We need to return a NaN if either operand is a
// NaN, so we explicitly check for a NaN in the read-write operand.
if (handleNaN) {
bind(&nan);
vucomiss(first, first);
j(Assembler::Parity, &done);
}
// When the values are inequal, or second is NaN, x86's min and max will
// return the value we need.
bind(&minMaxInst);
if (isMax)
vmaxss(second, first, first);
else
vminss(second, first, first);
bind(&done);
}
//{{{ check_macroassembler_style
// ===============================================================
// MacroAssembler high-level usage.

Просмотреть файл

@ -102,6 +102,11 @@ class MacroAssemblerX86Shared : public Assembler
bool asmMergeWith(const MacroAssemblerX86Shared& other);
// Evaluate first = minmax<isMax>(first, second).
// Handle NaN specially if handleNaN is true.
void minMaxDouble(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax);
void minMaxFloat32(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax);
void compareDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs) {
if (cond & DoubleConditionBitInvert)
vucomisd(lhs, rhs);