Bug 1176230 - Try to fold ternary's with double-argument to NaNToZero. r=nbp

This commit is contained in:
Johannes Schulte 2016-06-24 19:02:23 +02:00
Родитель 41dba26ec2
Коммит 3f3c70ceb2
13 изменённых файлов: 201 добавлений и 3 удалений

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

@ -11990,5 +11990,48 @@ CodeGenerator::visitRotate(LRotate* ins)
}
}
class OutOfLineNaNToZero : public OutOfLineCodeBase<CodeGenerator>
{
LNaNToZero* lir_;
public:
explicit OutOfLineNaNToZero(LNaNToZero* lir)
: lir_(lir)
{}
void accept(CodeGenerator* codegen) {
codegen->visitOutOfLineNaNToZero(this);
}
LNaNToZero* lir() const {
return lir_;
}
};
void
CodeGenerator::visitOutOfLineNaNToZero(OutOfLineNaNToZero* ool)
{
FloatRegister output = ToFloatRegister(ool->lir()->output());
masm.loadConstantDouble(0.0, output);
masm.jump(ool->rejoin());
}
void
CodeGenerator::visitNaNToZero(LNaNToZero* lir)
{
FloatRegister input = ToFloatRegister(lir->input());
OutOfLineNaNToZero* ool = new(alloc()) OutOfLineNaNToZero(lir);
addOutOfLineCode(ool, lir->mir());
if (lir->mir()->operandIsNeverNegativeZero()){
masm.branchDouble(Assembler::DoubleUnordered, input, input, ool->entry());
} else {
FloatRegister scratch = ToFloatRegister(lir->tempDouble());
masm.loadConstantDouble(0.0, scratch);
masm.branchDouble(Assembler::DoubleEqualOrUnordered, input, scratch, ool->entry());
}
masm.bind(ool->rejoin());
}
} // namespace jit
} // namespace js

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

@ -52,6 +52,7 @@ class OutOfLineRegExpTester;
class OutOfLineRegExpPrototypeOptimizable;
class OutOfLineRegExpInstanceOptimizable;
class OutOfLineLambdaArrow;
class OutOfLineNaNToZero;
class CodeGenerator final : public CodeGeneratorSpecific
{
@ -383,6 +384,8 @@ class CodeGenerator final : public CodeGeneratorSpecific
void visitCheckIsObj(LCheckIsObj* ins);
void visitCheckObjCoercible(LCheckObjCoercible* ins);
void visitDebugCheckSelfHosted(LDebugCheckSelfHosted* ins);
void visitNaNToZero(LNaNToZero* ins);
void visitOutOfLineNaNToZero(OutOfLineNaNToZero* ool);
void visitCheckOverRecursed(LCheckOverRecursed* lir);
void visitCheckOverRecursedFailure(CheckOverRecursedFailure* ool);

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

@ -4841,6 +4841,19 @@ LIRGenerator::visitBlock(MBasicBlock* block)
return true;
}
void
LIRGenerator::visitNaNToZero(MNaNToZero *ins)
{
MDefinition* input = ins->input();
if (ins->operandIsNeverNaN() && ins->operandIsNeverNegativeZero()) {
redefine(ins, input);
return;
}
LNaNToZero* lir = new(alloc()) LNaNToZero(useRegisterAtStart(input), tempDouble());
defineReuseInput(lir, ins, 0);
}
bool
LIRGenerator::generate()
{

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

@ -322,6 +322,7 @@ class LIRGenerator : public LIRGeneratorSpecific
void visitDebugger(MDebugger* ins);
void visitNewTarget(MNewTarget* ins);
void visitArrowNewTarget(MArrowNewTarget* ins);
void visitNaNToZero(MNaNToZero *ins);
void visitAtomicIsLockFree(MAtomicIsLockFree* ins);
void visitGuardSharedTypedArray(MGuardSharedTypedArray* ins);
void visitCheckReturn(MCheckReturn* ins);

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

@ -2326,7 +2326,7 @@ MPhi::removeAllOperands()
}
MDefinition*
MPhi::foldsTernary()
MPhi::foldsTernary(TempAllocator& alloc)
{
/* Look if this MPhi is a ternary construct.
* This is a very loose term as it actually only checks for
@ -2416,6 +2416,14 @@ MPhi::foldsTernary()
return trueDef;
}
// If testArg is an double type we can:
// - fold testArg ? testArg : 0.0 to MNaNToZero(testArg)
if (testArg->type() == MIRType::Double && c->numberToDouble() == 0 && c != trueDef) {
MNaNToZero* replace = MNaNToZero::New(alloc, testArg);
test->block()->insertBefore(test, replace);
return replace;
}
// If testArg is a string type we can:
// - fold testArg ? testArg : "" to testArg
// - fold testArg ? "" : testArg to ""
@ -2495,7 +2503,7 @@ MPhi::foldsTo(TempAllocator& alloc)
if (MDefinition* def = operandIfRedundant())
return def;
if (MDefinition* def = foldsTernary())
if (MDefinition* def = foldsTernary(alloc))
return def;
if (MDefinition* def = foldsFilterTypeSet())

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

@ -7656,7 +7656,7 @@ class MPhi final
bool checkForTypeChange(TempAllocator& alloc, MDefinition* ins, bool* ptypeChange);
MDefinition* foldsTo(TempAllocator& alloc) override;
MDefinition* foldsTernary();
MDefinition* foldsTernary(TempAllocator& alloc);
MDefinition* foldsFilterTypeSet();
bool congruentTo(const MDefinition* ins) const override;
@ -7730,6 +7730,47 @@ class MBeta
void computeRange(TempAllocator& alloc) override;
};
// If input evaluates to false (i.e. it's NaN, 0 or -0), 0 is returned, else the input is returned
class MNaNToZero
: public MUnaryInstruction,
public DoublePolicy<0>::Data
{
bool operandIsNeverNaN_;
bool operandIsNeverNegativeZero_;
explicit MNaNToZero(MDefinition* input)
: MUnaryInstruction(input), operandIsNeverNaN_(false), operandIsNeverNegativeZero_(false)
{
setResultType(MIRType::Double);
setMovable();
}
public:
INSTRUCTION_HEADER(NaNToZero)
TRIVIAL_NEW_WRAPPERS
bool operandIsNeverNaN() const {
return operandIsNeverNaN_;
}
bool operandIsNeverNegativeZero() const {
return operandIsNeverNegativeZero_;
}
void collectRangeInfoPreTrunc() override;
AliasSet getAliasSet() const override {
return AliasSet::None();
}
void computeRange(TempAllocator& alloc) override;
bool writeRecoverData(CompactBufferWriter& writer) const override;
bool canRecoverOnBailout() const override {
return true;
}
ALLOW_CLONE(MNaNToZero)
};
// MIR representation of a Value on the OSR BaselineFrame.
// The Value is indexed off of OsrFrameReg.
class MOsrValue

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

@ -46,6 +46,7 @@ namespace jit {
_(Compare) \
_(Phi) \
_(Beta) \
_(NaNToZero) \
_(OsrValue) \
_(OsrEnvironmentChain) \
_(OsrReturnValue) \

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

@ -1217,6 +1217,16 @@ Range::sign(TempAllocator& alloc, const Range* op)
0);
}
Range*
Range::NaNToZero(TempAllocator& alloc, const Range *op)
{
Range* copy = new(alloc) Range(*op);
if (copy->canBeNaN())
copy->max_exponent_ = Range::IncludesInfinity;
copy->refineToExcludeNegativeZero();
return copy;
}
bool
Range::negativeZeroMul(const Range* lhs, const Range* rhs)
{
@ -1874,6 +1884,13 @@ MRandom::computeRange(TempAllocator& alloc)
setRange(r);
}
void
MNaNToZero::computeRange(TempAllocator& alloc)
{
Range other(input());
setRange(Range::NaNToZero(alloc, &other));
}
///////////////////////////////////////////////////////////////////////////////
// Range Analysis
///////////////////////////////////////////////////////////////////////////////
@ -3466,6 +3483,17 @@ MBinaryBitwiseInstruction::collectRangeInfoPreTrunc()
}
}
void
MNaNToZero::collectRangeInfoPreTrunc()
{
Range inputRange(input());
if (!inputRange.canBeNaN())
operandIsNeverNaN_ = true;
if (!inputRange.canBeNegativeZero())
operandIsNeverNegativeZero_ = true;
}
bool
RangeAnalysis::prepareForUCE(bool* shouldRemoveDeadCode)
{

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

@ -482,6 +482,7 @@ class Range : public TempObject {
static Range* floor(TempAllocator& alloc, const Range* op);
static Range* ceil(TempAllocator& alloc, const Range* op);
static Range* sign(TempAllocator& alloc, const Range* op);
static Range* NaNToZero(TempAllocator& alloc, const Range* op);
static MOZ_MUST_USE bool negativeZeroMul(const Range* lhs, const Range* rhs);

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

@ -1051,6 +1051,31 @@ RStringSplit::recover(JSContext* cx, SnapshotIterator& iter) const
return true;
}
bool
MNaNToZero::writeRecoverData(CompactBufferWriter& writer) const
{
MOZ_ASSERT(canRecoverOnBailout());
writer.writeUnsigned(uint32_t(RInstruction::Recover_NaNToZero));
return true;
}
RNaNToZero::RNaNToZero(CompactBufferReader& reader)
{ }
bool
RNaNToZero::recover(JSContext* cx, SnapshotIterator& iter) const
{
RootedValue v(cx, iter.read());
RootedValue result(cx);
MOZ_ASSERT(v.isDouble());
result.setDouble((mozilla::IsNaN(v.toDouble()) || mozilla::IsNegativeZero(v.toDouble())) ? 0.0 : v.toDouble());
iter.storeInstructionResult(result);
return true;
}
bool
MRegExpMatcher::writeRecoverData(CompactBufferWriter& writer) const
{

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

@ -90,6 +90,7 @@ namespace jit {
_(MathFunction) \
_(Random) \
_(StringSplit) \
_(NaNToZero) \
_(RegExpMatcher) \
_(RegExpSearcher) \
_(RegExpTester) \
@ -478,6 +479,14 @@ class RStringSplit final : public RInstruction
MOZ_MUST_USE bool recover(JSContext* cx, SnapshotIterator& iter) const;
};
class RNaNToZero final : public RInstruction
{
public:
RINSTRUCTION_HEADER_NUM_OP_(NaNToZero, 1);
bool recover(JSContext* cx, SnapshotIterator& iter) const;
};
class RRegExpMatcher final : public RInstruction
{
public:

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

@ -4566,6 +4566,30 @@ class LStart : public LInstructionHelper<0, 0, 0>
LIR_HEADER(Start)
};
class LNaNToZero : public LInstructionHelper<1, 1, 1>
{
public:
LIR_HEADER(NaNToZero)
explicit LNaNToZero(const LAllocation& input, const LDefinition& tempDouble) {
setOperand(0, input);
setTemp(0, tempDouble);
}
const MNaNToZero* mir() {
return mir_->toNaNToZero();
}
const LAllocation* input() {
return getOperand(0);
}
const LDefinition* output() {
return getDef(0);
}
const LDefinition* tempDouble() {
return getTemp(0);
}
};
// Passed the BaselineFrame address in the OsrFrameReg by SideCannon().
// Forwards this object to the LOsrValues for Value materialization.
class LOsrEntry : public LInstructionHelper<1, 0, 1>

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

@ -222,6 +222,7 @@
_(Float32x4ToInt32x4) \
_(Float32x4ToUint32x4) \
_(Start) \
_(NaNToZero) \
_(OsrEntry) \
_(OsrValue) \
_(OsrEnvironmentChain) \