Bug 1278283 - Expose max and min in the MacroAssembler + move ARM code. r=nbp

--HG--
extra : rebase_source : 55c92ea3f367bb11939b65ec8ea8ff95cf4bfcc2
This commit is contained in:
Lars T Hansen 2016-06-28 13:39:28 +02:00
Родитель d869ef34b6
Коммит af5d06cbe3
9 изменённых файлов: 197 добавлений и 87 удалений

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

@ -816,6 +816,15 @@ class MacroAssembler : public MacroAssemblerSpecific
inline void sqrtFloat32(FloatRegister src, FloatRegister dest) DEFINED_ON(arm, arm64, x86_shared); inline void sqrtFloat32(FloatRegister src, FloatRegister dest) DEFINED_ON(arm, arm64, x86_shared);
inline void sqrtDouble(FloatRegister src, FloatRegister dest) DEFINED_ON(arm, arm64, x86_shared); inline void sqrtDouble(FloatRegister src, FloatRegister dest) DEFINED_ON(arm, arm64, x86_shared);
// srcDest = {min,max}{Float32,Double}(srcDest, other)
// For min and max, handle NaN specially if handleNaN is true.
inline void minFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN) DEFINED_ON(arm, arm64, x86_shared);
inline void minDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN) DEFINED_ON(arm, arm64, x86_shared);
inline void maxFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN) DEFINED_ON(arm, arm64, x86_shared);
inline void maxDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN) DEFINED_ON(arm, arm64, x86_shared);
// =============================================================== // ===============================================================
// Shift functions // Shift functions

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

@ -213,47 +213,13 @@ CodeGeneratorARM::visitMinMaxD(LMinMaxD* ins)
{ {
FloatRegister first = ToFloatRegister(ins->first()); FloatRegister first = ToFloatRegister(ins->first());
FloatRegister second = ToFloatRegister(ins->second()); FloatRegister second = ToFloatRegister(ins->second());
FloatRegister output = ToFloatRegister(ins->output());
MOZ_ASSERT(first == output); MOZ_ASSERT(first == ToFloatRegister(ins->output()));
Assembler::Condition cond = ins->mir()->isMax() if (ins->mir()->isMax())
? Assembler::VFP_LessThanOrEqual masm.maxDouble(second, first, true);
: Assembler::VFP_GreaterThanOrEqual; else
Label nan, equal, returnSecond, done; masm.minDouble(second, first, true);
masm.compareDouble(first, second);
// First or second is NaN, result is NaN.
masm.ma_b(&nan, Assembler::VFP_Unordered);
// Make sure we handle -0 and 0 right.
masm.ma_b(&equal, Assembler::VFP_Equal);
masm.ma_b(&returnSecond, cond);
masm.ma_b(&done);
// Check for zero.
masm.bind(&equal);
masm.compareDouble(first, NoVFPRegister);
// First wasn't 0 or -0, so just return it.
masm.ma_b(&done, Assembler::VFP_NotEqualOrUnordered);
// So now both operands are either -0 or 0.
if (ins->mir()->isMax()) {
// -0 + -0 = -0 and -0 + 0 = 0.
masm.ma_vadd(second, first, first);
} else {
masm.ma_vneg(first, first);
masm.ma_vsub(first, second, first);
masm.ma_vneg(first, first);
}
masm.ma_b(&done);
masm.bind(&nan);
masm.loadConstantDouble(GenericNaN(), output);
masm.ma_b(&done);
masm.bind(&returnSecond);
masm.ma_vmov(second, output);
masm.bind(&done);
} }
void void
@ -261,47 +227,13 @@ CodeGeneratorARM::visitMinMaxF(LMinMaxF* ins)
{ {
FloatRegister first = ToFloatRegister(ins->first()); FloatRegister first = ToFloatRegister(ins->first());
FloatRegister second = ToFloatRegister(ins->second()); FloatRegister second = ToFloatRegister(ins->second());
FloatRegister output = ToFloatRegister(ins->output());
MOZ_ASSERT(first == output); MOZ_ASSERT(first == ToFloatRegister(ins->output()));
Assembler::Condition cond = ins->mir()->isMax() if (ins->mir()->isMax())
? Assembler::VFP_LessThanOrEqual masm.maxFloat32(second, first, true);
: Assembler::VFP_GreaterThanOrEqual; else
Label nan, equal, returnSecond, done; masm.minFloat32(second, first, true);
masm.compareFloat(first, second);
// First or second is NaN, result is NaN.
masm.ma_b(&nan, Assembler::VFP_Unordered);
// Make sure we handle -0 and 0 right.
masm.ma_b(&equal, Assembler::VFP_Equal);
masm.ma_b(&returnSecond, cond);
masm.ma_b(&done);
// Check for zero.
masm.bind(&equal);
masm.compareFloat(first, NoVFPRegister);
// First wasn't 0 or -0, so just return it.
masm.ma_b(&done, Assembler::VFP_NotEqualOrUnordered);
// So now both operands are either -0 or 0.
if (ins->mir()->isMax()) {
// -0 + -0 = -0 and -0 + 0 = 0.
masm.ma_vadd_f32(second, first, first);
} else {
masm.ma_vneg_f32(first, first);
masm.ma_vsub_f32(first, second, first);
masm.ma_vneg_f32(first, first);
}
masm.ma_b(&done);
masm.bind(&nan);
masm.loadConstantFloat32(GenericNaN(), output);
masm.ma_b(&done);
masm.bind(&returnSecond);
masm.ma_vmov_f32(second, output);
masm.bind(&done);
} }
void void

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

@ -484,6 +484,30 @@ MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest)
ma_vsqrt(src, dest); ma_vsqrt(src, dest);
} }
void
MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxFloat32(srcDest, other, handleNaN, false);
}
void
MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxDouble(srcDest, other, handleNaN, false);
}
void
MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxFloat32(srcDest, other, handleNaN, true);
}
void
MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxDouble(srcDest, other, handleNaN, true);
}
// =============================================================== // ===============================================================
// Shift functions // Shift functions

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

@ -2450,6 +2450,94 @@ MacroAssemblerARMCompat::setStackArg(Register reg, uint32_t arg)
ma_dataTransferN(IsStore, 32, true, sp, Imm32(arg * sizeof(intptr_t)), reg); ma_dataTransferN(IsStore, 32, true, sp, Imm32(arg * sizeof(intptr_t)), reg);
} }
void
MacroAssemblerARMCompat::minMaxDouble(FloatRegister srcDest, FloatRegister second, bool handleNaN, bool isMax)
{
FloatRegister first = srcDest;
Assembler::Condition cond = isMax
? Assembler::VFP_LessThanOrEqual
: Assembler::VFP_GreaterThanOrEqual;
Label nan, equal, returnSecond, done;
compareDouble(first, second);
// First or second is NaN, result is NaN.
ma_b(&nan, Assembler::VFP_Unordered);
// Make sure we handle -0 and 0 right.
ma_b(&equal, Assembler::VFP_Equal);
ma_b(&returnSecond, cond);
ma_b(&done);
// Check for zero.
bind(&equal);
compareDouble(first, NoVFPRegister);
// First wasn't 0 or -0, so just return it.
ma_b(&done, Assembler::VFP_NotEqualOrUnordered);
// So now both operands are either -0 or 0.
if (isMax) {
// -0 + -0 = -0 and -0 + 0 = 0.
ma_vadd(second, first, first);
} else {
ma_vneg(first, first);
ma_vsub(first, second, first);
ma_vneg(first, first);
}
ma_b(&done);
bind(&nan);
loadConstantDouble(JS::GenericNaN(), srcDest);
ma_b(&done);
bind(&returnSecond);
ma_vmov(second, srcDest);
bind(&done);
}
void
MacroAssemblerARMCompat::minMaxFloat32(FloatRegister srcDest, FloatRegister second, bool handleNaN, bool isMax)
{
FloatRegister first = srcDest;
Assembler::Condition cond = isMax
? Assembler::VFP_LessThanOrEqual
: Assembler::VFP_GreaterThanOrEqual;
Label nan, equal, returnSecond, done;
compareFloat(first, second);
// First or second is NaN, result is NaN.
ma_b(&nan, Assembler::VFP_Unordered);
// Make sure we handle -0 and 0 right.
ma_b(&equal, Assembler::VFP_Equal);
ma_b(&returnSecond, cond);
ma_b(&done);
// Check for zero.
bind(&equal);
compareFloat(first, NoVFPRegister);
// First wasn't 0 or -0, so just return it.
ma_b(&done, Assembler::VFP_NotEqualOrUnordered);
// So now both operands are either -0 or 0.
if (isMax) {
// -0 + -0 = -0 and -0 + 0 = 0.
ma_vadd_f32(second, first, first);
} else {
ma_vneg_f32(first, first);
ma_vsub_f32(first, second, first);
ma_vneg_f32(first, first);
}
ma_b(&done);
bind(&nan);
loadConstantFloat32(float(JS::GenericNaN()), srcDest);
ma_b(&done);
bind(&returnSecond);
ma_vmov_f32(second, srcDest);
bind(&done);
}
void void
MacroAssemblerARMCompat::compareDouble(FloatRegister lhs, FloatRegister rhs) MacroAssemblerARMCompat::compareDouble(FloatRegister lhs, FloatRegister rhs)
{ {

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

@ -1324,6 +1324,11 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
// (On non-simulator builds, does nothing.) // (On non-simulator builds, does nothing.)
void simulatorStop(const char* msg); void simulatorStop(const char* msg);
// Evaluate srcDest = minmax<isMax>{Float32,Double}(srcDest, other).
// Handle NaN specially if handleNaN is true.
void minMaxDouble(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax);
void minMaxFloat32(FloatRegister srcDest, FloatRegister other, bool handleNaN, bool isMax);
void compareDouble(FloatRegister lhs, FloatRegister rhs); void compareDouble(FloatRegister lhs, FloatRegister rhs);
void compareFloat(FloatRegister lhs, FloatRegister rhs); void compareFloat(FloatRegister lhs, FloatRegister rhs);

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

@ -511,6 +511,30 @@ MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest)
MOZ_CRASH("NYI - sqrtDouble"); MOZ_CRASH("NYI - sqrtDouble");
} }
void
MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
MOZ_CRASH("NYI - minFloat32");
}
void
MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
MOZ_CRASH("NYI - minDouble");
}
void
MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
MOZ_CRASH("NYI - maxFloat32");
}
void
MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
MOZ_CRASH("NYI - maxDouble");
}
// =============================================================== // ===============================================================
// Shift functions // Shift functions

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

@ -666,10 +666,12 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD* ins)
MOZ_ASSERT(first == output); MOZ_ASSERT(first == output);
#endif #endif
bool specialHandling = !ins->mir()->range() || ins->mir()->range()->canBeNaN(); bool handleNaN = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
bool isMax = ins->mir()->isMax();
masm.minMaxDouble(first, second, specialHandling, isMax); if (ins->mir()->isMax())
masm.maxDouble(second, first, handleNaN);
else
masm.minDouble(second, first, handleNaN);
} }
void void
@ -682,10 +684,12 @@ CodeGeneratorX86Shared::visitMinMaxF(LMinMaxF* ins)
MOZ_ASSERT(first == output); MOZ_ASSERT(first == output);
#endif #endif
bool specialHandling = !ins->mir()->range() || ins->mir()->range()->canBeNaN(); bool handleNaN = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
bool isMax = ins->mir()->isMax();
masm.minMaxFloat32(first, second, specialHandling, isMax); if (ins->mir()->isMax())
masm.maxFloat32(second, first, handleNaN);
else
masm.minFloat32(second, first, handleNaN);
} }
void void

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

@ -339,6 +339,30 @@ MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest)
vsqrtsd(src, src, dest); vsqrtsd(src, src, dest);
} }
void
MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxFloat32(srcDest, other, handleNaN, false);
}
void
MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxDouble(srcDest, other, handleNaN, false);
}
void
MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxFloat32(srcDest, other, handleNaN, true);
}
void
MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
{
minMaxDouble(srcDest, other, handleNaN, true);
}
// =============================================================== // ===============================================================
// Rotation instructions // Rotation instructions
void void

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

@ -102,10 +102,10 @@ class MacroAssemblerX86Shared : public Assembler
bool asmMergeWith(const MacroAssemblerX86Shared& other); bool asmMergeWith(const MacroAssemblerX86Shared& other);
// Evaluate first = minmax<isMax>(first, second). // Evaluate srcDest = minmax<isMax>{Float32,Double}(srcDest, second).
// Handle NaN specially if handleNaN is true. // Handle NaN specially if handleNaN is true.
void minMaxDouble(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax); void minMaxDouble(FloatRegister srcDest, FloatRegister second, bool handleNaN, bool isMax);
void minMaxFloat32(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax); void minMaxFloat32(FloatRegister srcDest, FloatRegister second, bool handleNaN, bool isMax);
void outOfLineWasmTruncateCheck(FloatRegister input, MIRType fromType, MIRType toType, void outOfLineWasmTruncateCheck(FloatRegister input, MIRType fromType, MIRType toType,
bool isUnsigned, Label* rejoin); bool isUnsigned, Label* rejoin);