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:
Benjamin Bouvier 2013-10-22 14:53:12 +02:00
parent 10f5a55e22
commit 7f3147dfed
15 changed files with 115 additions and 6 deletions

View File

@ -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",

View File

@ -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>
{

View File

@ -101,6 +101,7 @@
_(NegF) \
_(AbsI) \
_(AbsD) \
_(AbsF) \
_(SqrtD) \
_(SqrtF) \
_(Atan2D) \

View File

@ -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);
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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().

View File

@ -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)
{

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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());

View File

@ -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)
{

View File

@ -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);

View File

@ -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 */