зеркало из 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 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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче