зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1278283
- Expose max and min in the MacroAssembler + move ARM code. r=nbp
--HG-- extra : rebase_source : 55c92ea3f367bb11939b65ec8ea8ff95cf4bfcc2
This commit is contained in:
Родитель
d869ef34b6
Коммит
af5d06cbe3
|
@ -816,6 +816,15 @@ class MacroAssembler : public MacroAssemblerSpecific
|
|||
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);
|
||||
|
||||
// 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
|
||||
|
||||
|
|
|
@ -213,47 +213,13 @@ CodeGeneratorARM::visitMinMaxD(LMinMaxD* ins)
|
|||
{
|
||||
FloatRegister first = ToFloatRegister(ins->first());
|
||||
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()
|
||||
? Assembler::VFP_LessThanOrEqual
|
||||
: Assembler::VFP_GreaterThanOrEqual;
|
||||
Label nan, equal, returnSecond, done;
|
||||
|
||||
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);
|
||||
if (ins->mir()->isMax())
|
||||
masm.maxDouble(second, first, true);
|
||||
else
|
||||
masm.minDouble(second, first, true);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -261,47 +227,13 @@ CodeGeneratorARM::visitMinMaxF(LMinMaxF* ins)
|
|||
{
|
||||
FloatRegister first = ToFloatRegister(ins->first());
|
||||
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()
|
||||
? Assembler::VFP_LessThanOrEqual
|
||||
: Assembler::VFP_GreaterThanOrEqual;
|
||||
Label nan, equal, returnSecond, done;
|
||||
|
||||
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);
|
||||
if (ins->mir()->isMax())
|
||||
masm.maxFloat32(second, first, true);
|
||||
else
|
||||
masm.minFloat32(second, first, true);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -484,6 +484,30 @@ MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister 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
|
||||
|
||||
|
|
|
@ -2450,6 +2450,94 @@ MacroAssemblerARMCompat::setStackArg(Register reg, uint32_t arg)
|
|||
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
|
||||
MacroAssemblerARMCompat::compareDouble(FloatRegister lhs, FloatRegister rhs)
|
||||
{
|
||||
|
|
|
@ -1324,6 +1324,11 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
|||
// (On non-simulator builds, does nothing.)
|
||||
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 compareFloat(FloatRegister lhs, FloatRegister rhs);
|
||||
|
|
|
@ -511,6 +511,30 @@ MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest)
|
|||
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
|
||||
|
||||
|
|
|
@ -666,10 +666,12 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD* ins)
|
|||
MOZ_ASSERT(first == output);
|
||||
#endif
|
||||
|
||||
bool specialHandling = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
|
||||
bool isMax = ins->mir()->isMax();
|
||||
bool handleNaN = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
|
||||
|
||||
masm.minMaxDouble(first, second, specialHandling, isMax);
|
||||
if (ins->mir()->isMax())
|
||||
masm.maxDouble(second, first, handleNaN);
|
||||
else
|
||||
masm.minDouble(second, first, handleNaN);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -682,10 +684,12 @@ CodeGeneratorX86Shared::visitMinMaxF(LMinMaxF* ins)
|
|||
MOZ_ASSERT(first == output);
|
||||
#endif
|
||||
|
||||
bool specialHandling = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
|
||||
bool isMax = ins->mir()->isMax();
|
||||
bool handleNaN = !ins->mir()->range() || ins->mir()->range()->canBeNaN();
|
||||
|
||||
masm.minMaxFloat32(first, second, specialHandling, isMax);
|
||||
if (ins->mir()->isMax())
|
||||
masm.maxFloat32(second, first, handleNaN);
|
||||
else
|
||||
masm.minFloat32(second, first, handleNaN);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -339,6 +339,30 @@ MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister 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
|
||||
void
|
||||
|
|
|
@ -102,10 +102,10 @@ class MacroAssemblerX86Shared : public Assembler
|
|||
|
||||
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.
|
||||
void minMaxDouble(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax);
|
||||
void minMaxFloat32(FloatRegister first, FloatRegister second, bool handleNaN, bool isMax);
|
||||
void minMaxDouble(FloatRegister srcDest, FloatRegister second, bool handleNaN, bool isMax);
|
||||
void minMaxFloat32(FloatRegister srcDest, FloatRegister second, bool handleNaN, bool isMax);
|
||||
|
||||
void outOfLineWasmTruncateCheck(FloatRegister input, MIRType fromType, MIRType toType,
|
||||
bool isUnsigned, Label* rejoin);
|
||||
|
|
Загрузка…
Ссылка в новой задаче