зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1094052 - IonMonkey: Fix range analysis for Math.sign(-0) r=nbp,h4writer
This commit is contained in:
Родитель
70982a275f
Коммит
13dc791112
|
@ -1115,6 +1115,19 @@ Range::ceil(TempAllocator &alloc, const Range *op)
|
|||
return copy;
|
||||
}
|
||||
|
||||
Range *
|
||||
Range::sign(TempAllocator &alloc, const Range *op)
|
||||
{
|
||||
if (op->canBeNaN())
|
||||
return nullptr;
|
||||
|
||||
return new(alloc) Range(Max(Min(op->lower_, 1), -1),
|
||||
Max(Min(op->upper_, 1), -1),
|
||||
Range::ExcludesFractionalParts,
|
||||
NegativeZeroFlag(op->canBeNegativeZero()),
|
||||
0);
|
||||
}
|
||||
|
||||
bool
|
||||
Range::negativeZeroMul(const Range *lhs, const Range *rhs)
|
||||
{
|
||||
|
@ -1707,16 +1720,7 @@ MMathFunction::computeRange(TempAllocator &alloc)
|
|||
setRange(Range::NewDoubleRange(alloc, -1.0, 1.0));
|
||||
break;
|
||||
case Sign:
|
||||
if (!opRange.canBeNaN()) {
|
||||
// Note that Math.sign(-0) is -0, and we treat -0 as equal to 0.
|
||||
int32_t lower = -1;
|
||||
int32_t upper = 1;
|
||||
if (opRange.hasInt32LowerBound() && opRange.lower() >= 0)
|
||||
lower = 0;
|
||||
if (opRange.hasInt32UpperBound() && opRange.upper() <= 0)
|
||||
upper = 0;
|
||||
setRange(Range::NewInt32Range(alloc, lower, upper));
|
||||
}
|
||||
setRange(Range::sign(alloc, &opRange));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -472,6 +472,7 @@ class Range : public TempObject {
|
|||
static Range *max(TempAllocator &alloc, const Range *lhs, const Range *rhs);
|
||||
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 bool negativeZeroMul(const Range *lhs, const Range *rhs);
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ if CONFIG['ENABLE_ION']:
|
|||
'testJitGVN.cpp',
|
||||
'testJitMoveEmitterCycles-mips.cpp',
|
||||
'testJitMoveEmitterCycles.cpp',
|
||||
'testJitRangeAnalysis.cpp',
|
||||
'testJitRValueAlloc.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "jit/MIRGenerator.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "jit/ValueNumbering.h"
|
||||
#include "jit/RangeAnalysis.h"
|
||||
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
@ -81,6 +82,28 @@ struct MinimalFunc
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool runRangeAnalysis()
|
||||
{
|
||||
if (!SplitCriticalEdges(graph))
|
||||
return false;
|
||||
if (!RenumberBlocks(graph))
|
||||
return false;
|
||||
if (!BuildDominatorTree(graph))
|
||||
return false;
|
||||
if (!BuildPhiReverseMapping(graph))
|
||||
return false;
|
||||
RangeAnalysis rangeAnalysis(&mir, graph);
|
||||
if (!rangeAnalysis.addBetaNodes())
|
||||
return false;
|
||||
if (!rangeAnalysis.analyze())
|
||||
return false;
|
||||
if (!rangeAnalysis.addRangeAssertions())
|
||||
return false;
|
||||
if (!rangeAnalysis.removeBetaNodes())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
*/
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "jit/IonAnalysis.h"
|
||||
#include "jit/MIRGenerator.h"
|
||||
#include "jit/MIRGraph.h"
|
||||
#include "jit/RangeAnalysis.h"
|
||||
|
||||
#include "jsapi-tests/testJitMinimalFunc.h"
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::jit;
|
||||
|
||||
BEGIN_TEST(testJitRangeAnalysis_MathSign)
|
||||
{
|
||||
MinimalFunc func;
|
||||
MBasicBlock *block = func.createEntryBlock();
|
||||
|
||||
MParameter *p = func.createParameter();
|
||||
block->add(p);
|
||||
|
||||
MConstant *nan = MConstant::New(func.alloc, DoubleValue(JS::GenericNaN()));
|
||||
block->add(nan);
|
||||
MConstant *neginf = MConstant::New(func.alloc, DoubleValue(mozilla::NegativeInfinity<double>()));
|
||||
block->add(neginf);
|
||||
MConstant *negthreehalves = MConstant::New(func.alloc, DoubleValue(-1.5));
|
||||
block->add(negthreehalves);
|
||||
MConstant *negone = MConstant::New(func.alloc, DoubleValue(-1.0));
|
||||
block->add(negone);
|
||||
MConstant *neghalf = MConstant::New(func.alloc, DoubleValue(-0.5));
|
||||
block->add(neghalf);
|
||||
MConstant *negzero = MConstant::New(func.alloc, DoubleValue(-0.0));
|
||||
block->add(negzero);
|
||||
MConstant *zero = MConstant::New(func.alloc, DoubleValue(0.0));
|
||||
block->add(zero);
|
||||
MConstant *half = MConstant::New(func.alloc, DoubleValue(0.5));
|
||||
block->add(half);
|
||||
MConstant *one = MConstant::New(func.alloc, DoubleValue(1.0));
|
||||
block->add(one);
|
||||
MConstant *threehalves = MConstant::New(func.alloc, DoubleValue(1.5));
|
||||
block->add(threehalves);
|
||||
MConstant *inf = MConstant::New(func.alloc, DoubleValue(mozilla::PositiveInfinity<double>()));
|
||||
block->add(inf);
|
||||
|
||||
CHECK(mozilla::IsNaN(nan->value().toNumber()));
|
||||
CHECK(mozilla::IsInfinite(neginf->value().toNumber()));
|
||||
CHECK(mozilla::IsNegative(neginf->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(negthreehalves->value().toNumber()));
|
||||
CHECK(mozilla::IsNegative(negthreehalves->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(negone->value().toNumber()));
|
||||
CHECK(mozilla::IsNegative(negone->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(neghalf->value().toNumber()));
|
||||
CHECK(mozilla::IsNegative(neghalf->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(negzero->value().toNumber()));
|
||||
CHECK(mozilla::IsNegative(negzero->value().toNumber()));
|
||||
CHECK(mozilla::IsNegativeZero(negzero->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(negzero->value().toNumber()));
|
||||
CHECK(!mozilla::IsNegative(zero->value().toNumber()));
|
||||
CHECK(!mozilla::IsNegativeZero(zero->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(half->value().toNumber()));
|
||||
CHECK(!mozilla::IsNegative(half->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(one->value().toNumber()));
|
||||
CHECK(!mozilla::IsNegative(one->value().toNumber()));
|
||||
CHECK(mozilla::IsFinite(threehalves->value().toNumber()));
|
||||
CHECK(!mozilla::IsNegative(threehalves->value().toNumber()));
|
||||
CHECK(mozilla::IsInfinite(inf->value().toNumber()));
|
||||
CHECK(!mozilla::IsNegative(inf->value().toNumber()));
|
||||
|
||||
MathCache cache;
|
||||
|
||||
MMathFunction *nanSign = MMathFunction::New(func.alloc, nan, MMathFunction::Sign, &cache);
|
||||
block->add(nanSign);
|
||||
MMathFunction *neginfSign = MMathFunction::New(func.alloc, neginf, MMathFunction::Sign, &cache);
|
||||
block->add(neginfSign);
|
||||
MMathFunction *negthreehalvesSign = MMathFunction::New(func.alloc, negthreehalves,
|
||||
MMathFunction::Sign, &cache);
|
||||
block->add(negthreehalvesSign);
|
||||
MMathFunction *negoneSign = MMathFunction::New(func.alloc, negone, MMathFunction::Sign, &cache);
|
||||
block->add(negoneSign);
|
||||
MMathFunction *neghalfSign = MMathFunction::New(func.alloc, neghalf, MMathFunction::Sign, &cache);
|
||||
block->add(neghalfSign);
|
||||
MMathFunction *negzeroSign = MMathFunction::New(func.alloc, negzero, MMathFunction::Sign, &cache);
|
||||
block->add(negzeroSign);
|
||||
MMathFunction *zeroSign = MMathFunction::New(func.alloc, zero, MMathFunction::Sign, &cache);
|
||||
block->add(zeroSign);
|
||||
MMathFunction *halfSign = MMathFunction::New(func.alloc, half, MMathFunction::Sign, &cache);
|
||||
block->add(halfSign);
|
||||
MMathFunction *oneSign = MMathFunction::New(func.alloc, one, MMathFunction::Sign, &cache);
|
||||
block->add(oneSign);
|
||||
MMathFunction *threehalvesSign = MMathFunction::New(func.alloc, threehalves,
|
||||
MMathFunction::Sign, &cache);
|
||||
block->add(threehalvesSign);
|
||||
MMathFunction *infSign = MMathFunction::New(func.alloc, inf, MMathFunction::Sign, &cache);
|
||||
block->add(infSign);
|
||||
|
||||
MReturn *ret = MReturn::New(func.alloc, p);
|
||||
block->end(ret);
|
||||
|
||||
if (!func.runRangeAnalysis())
|
||||
return false;
|
||||
|
||||
CHECK(!nanSign->range());
|
||||
CHECK(neginfSign->range()->isInt32());
|
||||
CHECK(neginfSign->range()->lower() == -1);
|
||||
CHECK(neginfSign->range()->upper() == -1);
|
||||
CHECK(negthreehalvesSign->range()->isInt32());
|
||||
CHECK(negthreehalvesSign->range()->lower() == -1);
|
||||
CHECK(negthreehalvesSign->range()->upper() == -1);
|
||||
CHECK(negoneSign->range()->isInt32());
|
||||
CHECK(negoneSign->range()->lower() == -1);
|
||||
CHECK(negoneSign->range()->upper() == -1);
|
||||
CHECK(neghalfSign->range()->isInt32());
|
||||
CHECK(neghalfSign->range()->lower() == -1);
|
||||
|
||||
// This should ideally be -1, but range analysis can't represent the
|
||||
// specific fractional range of the constant.
|
||||
CHECK(neghalfSign->range()->upper() == 0);
|
||||
|
||||
CHECK(!negzeroSign->range()->canHaveFractionalPart());
|
||||
CHECK(negzeroSign->range()->canBeNegativeZero());
|
||||
CHECK(negzeroSign->range()->lower() == 0);
|
||||
CHECK(negzeroSign->range()->upper() == 0);
|
||||
CHECK(!zeroSign->range()->canHaveFractionalPart());
|
||||
CHECK(!zeroSign->range()->canBeNegativeZero());
|
||||
CHECK(zeroSign->range()->lower() == 0);
|
||||
CHECK(zeroSign->range()->upper() == 0);
|
||||
CHECK(halfSign->range()->isInt32());
|
||||
|
||||
// This should ideally be 1, but range analysis can't represent the
|
||||
// specific fractional range of the constant.
|
||||
CHECK(halfSign->range()->lower() == 0);
|
||||
|
||||
CHECK(halfSign->range()->upper() == 1);
|
||||
CHECK(oneSign->range()->isInt32());
|
||||
CHECK(oneSign->range()->lower() == 1);
|
||||
CHECK(oneSign->range()->upper() == 1);
|
||||
CHECK(threehalvesSign->range()->isInt32());
|
||||
CHECK(threehalvesSign->range()->lower() == 1);
|
||||
CHECK(threehalvesSign->range()->upper() == 1);
|
||||
CHECK(infSign->range()->isInt32());
|
||||
CHECK(infSign->range()->lower() == 1);
|
||||
CHECK(infSign->range()->upper() == 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
END_TEST(testJitRangeAnalysis_MathSign)
|
|
@ -159,8 +159,8 @@ IsFinite(T aValue)
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether a float/double is negative. It is an error to call this
|
||||
* method on a float/double which is NaN.
|
||||
* Determines whether a float/double is negative or -0. It is an error
|
||||
* to call this method on a float/double which is NaN.
|
||||
*/
|
||||
template<typename T>
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче