mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 17:24:29 +00:00
Bug 913282: More Float32 operators: Abs; p=dougc,bbouvier; r=jonco,sstangl
dougc for the ARM parts, bbouvier for the rest.
This commit is contained in:
parent
10f5a55e22
commit
7f3147dfed
@ -2899,6 +2899,13 @@ public:
|
||||
m_formatter.twoByteOp(OP2_ANDPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
|
||||
}
|
||||
|
||||
void andps_rr(XMMRegisterID src, XMMRegisterID dst)
|
||||
{
|
||||
spew("andps %s, %s",
|
||||
nameFPReg(src), nameFPReg(dst));
|
||||
m_formatter.twoByteOp(OP2_ANDPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
|
||||
}
|
||||
|
||||
void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
|
||||
{
|
||||
spew("sqrtsd %s, %s",
|
||||
|
@ -2293,6 +2293,16 @@ class LAbsD : public LInstructionHelper<1, 1, 0>
|
||||
}
|
||||
};
|
||||
|
||||
// Absolute value of a float32.
|
||||
class LAbsF : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(AbsF)
|
||||
LAbsF(const LAllocation &num) {
|
||||
setOperand(0, num);
|
||||
}
|
||||
};
|
||||
|
||||
// Square root of a double.
|
||||
class LSqrtD : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
|
@ -101,6 +101,7 @@
|
||||
_(NegF) \
|
||||
_(AbsI) \
|
||||
_(AbsD) \
|
||||
_(AbsF) \
|
||||
_(SqrtD) \
|
||||
_(SqrtF) \
|
||||
_(Atan2D) \
|
||||
|
@ -1167,6 +1167,7 @@ bool
|
||||
LIRGenerator::visitAbs(MAbs *ins)
|
||||
{
|
||||
MDefinition *num = ins->num();
|
||||
JS_ASSERT(IsNumberType(num->type()));
|
||||
|
||||
if (num->type() == MIRType_Int32) {
|
||||
LAbsI *lir = new LAbsI(useRegisterAtStart(num));
|
||||
@ -1175,8 +1176,11 @@ LIRGenerator::visitAbs(MAbs *ins)
|
||||
return false;
|
||||
return defineReuseInput(lir, ins, 0);
|
||||
}
|
||||
if (num->type() == MIRType_Float32) {
|
||||
LAbsF *lir = new LAbsF(useRegisterAtStart(num));
|
||||
return defineReuseInput(lir, ins, 0);
|
||||
}
|
||||
|
||||
JS_ASSERT(num->type() == MIRType_Double);
|
||||
LAbsD *lir = new LAbsD(useRegisterAtStart(num));
|
||||
return defineReuseInput(lir, ins, 0);
|
||||
}
|
||||
|
@ -520,18 +520,27 @@ IonBuilder::inlineMathAbs(CallInfo &callInfo)
|
||||
|
||||
MIRType returnType = getInlineReturnType();
|
||||
MIRType argType = callInfo.getArg(0)->type();
|
||||
if (argType != MIRType_Int32 && argType != MIRType_Double)
|
||||
if (!IsNumberType(argType))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
if (argType != returnType && returnType != MIRType_Int32)
|
||||
// Either argType == returnType, or
|
||||
// argType == Double or Float32, returnType == Int, or
|
||||
// argType == Float32, returnType == Double
|
||||
if (argType != returnType && !(IsFloatingPointType(argType) && returnType == MIRType_Int32)
|
||||
&& !(argType == MIRType_Float32 && returnType == MIRType_Double))
|
||||
{
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
callInfo.unwrapArgs();
|
||||
|
||||
MInstruction *ins = MAbs::New(callInfo.getArg(0), argType);
|
||||
// If the arg is a Float32, we specialize the op as double, it will be specialized
|
||||
// as float32 if necessary later.
|
||||
MIRType absType = (argType == MIRType_Float32) ? MIRType_Double : argType;
|
||||
MInstruction *ins = MAbs::New(callInfo.getArg(0), absType);
|
||||
current->add(ins);
|
||||
|
||||
if (argType != returnType) {
|
||||
if (IsFloatingPointType(argType) && returnType == MIRType_Int32) {
|
||||
MToInt32 *toInt = MToInt32::New(ins);
|
||||
toInt->setCanBeNegativeZero(false);
|
||||
current->add(toInt);
|
||||
|
@ -1279,6 +1279,19 @@ MAbs::fallible() const
|
||||
return !implicitTruncate_ && (!range() || !range()->hasInt32Bounds());
|
||||
}
|
||||
|
||||
void
|
||||
MAbs::trySpecializeFloat32()
|
||||
{
|
||||
if (!input()->canProduceFloat32() || !CheckUsesAreFloat32Consumers(this)) {
|
||||
if (input()->type() == MIRType_Float32)
|
||||
ConvertDefinitionToDouble<0>(input(), this);
|
||||
return;
|
||||
}
|
||||
|
||||
setResultType(MIRType_Float32);
|
||||
specialization_ = MIRType_Float32;
|
||||
}
|
||||
|
||||
MDefinition *
|
||||
MDiv::foldsTo(bool useValueNumbers)
|
||||
{
|
||||
|
@ -3418,7 +3418,7 @@ class MAbs
|
||||
: MUnaryInstruction(num),
|
||||
implicitTruncate_(false)
|
||||
{
|
||||
JS_ASSERT(type == MIRType_Double || type == MIRType_Int32);
|
||||
JS_ASSERT(IsNumberType(type));
|
||||
setResultType(type);
|
||||
setMovable();
|
||||
specialization_ = type;
|
||||
@ -3450,6 +3450,8 @@ class MAbs
|
||||
return AliasSet::None();
|
||||
}
|
||||
void computeRange();
|
||||
bool isFloat32Commutative() const { return true; }
|
||||
void trySpecializeFloat32();
|
||||
};
|
||||
|
||||
// Inline implementation of Math.sqrt().
|
||||
|
@ -339,6 +339,15 @@ CodeGeneratorARM::visitAbsD(LAbsD *ins)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorARM::visitAbsF(LAbsF *ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
JS_ASSERT(input == ToFloatRegister(ins->output()));
|
||||
masm.ma_vabs_f32(input, input);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorARM::visitSqrtD(LSqrtD *ins)
|
||||
{
|
||||
|
@ -66,6 +66,7 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
||||
// Instruction visitors.
|
||||
virtual bool visitMinMaxD(LMinMaxD *ins);
|
||||
virtual bool visitAbsD(LAbsD *ins);
|
||||
virtual bool visitAbsF(LAbsF *ins);
|
||||
virtual bool visitSqrtD(LSqrtD *ins);
|
||||
virtual bool visitSqrtF(LSqrtF *ins);
|
||||
virtual bool visitAddI(LAddI *ins);
|
||||
|
@ -1425,6 +1425,12 @@ MacroAssemblerARM::ma_vabs(FloatRegister src, FloatRegister dest, Condition cc)
|
||||
as_vabs(dest, src, cc);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARM::ma_vabs_f32(FloatRegister src, FloatRegister dest, Condition cc)
|
||||
{
|
||||
as_vabs(VFPRegister(dest).singleOverlay(), VFPRegister(src).singleOverlay(), cc);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssemblerARM::ma_vsqrt(FloatRegister src, FloatRegister dest, Condition cc)
|
||||
{
|
||||
|
@ -317,6 +317,7 @@ class MacroAssemblerARM : public Assembler
|
||||
void ma_vneg(FloatRegister src, FloatRegister dest, Condition cc = Always);
|
||||
void ma_vmov(FloatRegister src, FloatRegister dest, Condition cc = Always);
|
||||
void ma_vabs(FloatRegister src, FloatRegister dest, Condition cc = Always);
|
||||
void ma_vabs_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
|
||||
|
||||
void ma_vsqrt(FloatRegister src, FloatRegister dest, Condition cc = Always);
|
||||
void ma_vsqrt_f32(FloatRegister src, FloatRegister dest, Condition cc = Always);
|
||||
|
@ -1448,6 +1448,10 @@ class AssemblerX86Shared
|
||||
JS_ASSERT(HasSSE2());
|
||||
masm.andpd_rr(src.code(), dest.code());
|
||||
}
|
||||
void andps(const FloatRegister &src, const FloatRegister &dest) {
|
||||
JS_ASSERT(HasSSE2());
|
||||
masm.andps_rr(src.code(), dest.code());
|
||||
}
|
||||
void sqrtsd(const FloatRegister &src, const FloatRegister &dest) {
|
||||
JS_ASSERT(HasSSE2());
|
||||
masm.sqrtsd_rr(src.code(), dest.code());
|
||||
|
@ -19,9 +19,11 @@ using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
using mozilla::DoubleSignificandBits;
|
||||
using mozilla::FloatSignificandBits;
|
||||
using mozilla::FloorLog2;
|
||||
using mozilla::NegativeInfinity;
|
||||
using mozilla::SpecificNaN;
|
||||
using mozilla::SpecificFloatNaN;
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
@ -473,6 +475,17 @@ CodeGeneratorX86Shared::visitAbsD(LAbsD *ins)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitAbsF(LAbsF *ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
JS_ASSERT(input == ToFloatRegister(ins->output()));
|
||||
// Same trick as visitAbsD above.
|
||||
masm.loadConstantFloat32(SpecificFloatNaN(0, FloatSignificandBits), ScratchFloatReg);
|
||||
masm.andps(ScratchFloatReg, input);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::visitSqrtD(LSqrtD *ins)
|
||||
{
|
||||
|
@ -82,6 +82,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||
virtual bool visitFloat32(LFloat32 *ins);
|
||||
virtual bool visitMinMaxD(LMinMaxD *ins);
|
||||
virtual bool visitAbsD(LAbsD *ins);
|
||||
virtual bool visitAbsF(LAbsF *ins);
|
||||
virtual bool visitSqrtD(LSqrtD *ins);
|
||||
virtual bool visitSqrtF(LSqrtF *ins);
|
||||
virtual bool visitPowHalfD(LPowHalfD *ins);
|
||||
|
@ -241,6 +241,34 @@ DoublesAreIdentical(double d1, double d2)
|
||||
return BitwiseCast<uint64_t>(d1) == BitwiseCast<uint64_t>(d2);
|
||||
}
|
||||
|
||||
/** Determines whether a float is NaN. */
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsFloatNaN(float f)
|
||||
{
|
||||
/*
|
||||
* A float is NaN if all exponent bits are 1 and the significand contains at
|
||||
* least one non-zero bit.
|
||||
*/
|
||||
uint32_t bits = BitwiseCast<uint32_t>(f);
|
||||
return (bits & FloatExponentBits) == FloatExponentBits &&
|
||||
(bits & FloatSignificandBits) != 0;
|
||||
}
|
||||
|
||||
/** Constructs a NaN value with the specified sign bit and significand bits. */
|
||||
static MOZ_ALWAYS_INLINE float
|
||||
SpecificFloatNaN(int signbit, uint32_t significand)
|
||||
{
|
||||
MOZ_ASSERT(signbit == 0 || signbit == 1);
|
||||
MOZ_ASSERT((significand & ~FloatSignificandBits) == 0);
|
||||
MOZ_ASSERT(significand & FloatSignificandBits);
|
||||
|
||||
float f = BitwiseCast<float>((signbit ? FloatSignBit : 0) |
|
||||
FloatExponentBits |
|
||||
significand);
|
||||
MOZ_ASSERT(IsFloatNaN(f));
|
||||
return f;
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_FloatingPoint_h */
|
||||
|
Loading…
x
Reference in New Issue
Block a user