Bug 915846 - IonMonkey: Introduce several new Range predicate helper functions. r=nbp

This commit is contained in:
Dan Gohman 2013-10-03 17:25:02 -07:00
parent 9d8d65f46f
commit 7b632205a2
3 changed files with 61 additions and 24 deletions

View File

@ -39,7 +39,10 @@ using namespace js;
using namespace js::jit;
using mozilla::DebugOnly;
using mozilla::DoubleExponentBias;
using mozilla::Maybe;
using mozilla::NegativeInfinity;
using mozilla::PositiveInfinity;
using JS::GenericNaN;
namespace js {
@ -7517,7 +7520,7 @@ bool
CodeGenerator::emitAssertRangeI(const Range *r, Register input)
{
// Check the lower bound.
if (r->lower() != INT32_MIN) {
if (r->hasInt32LowerBound() && r->lower() > INT32_MIN) {
Label success;
masm.branch32(Assembler::GreaterThanOrEqual, input, Imm32(r->lower()), &success);
masm.breakpoint();
@ -7525,7 +7528,7 @@ CodeGenerator::emitAssertRangeI(const Range *r, Register input)
}
// Check the upper bound.
if (r->upper() != INT32_MAX) {
if (r->hasInt32UpperBound() && r->upper() < INT32_MAX) {
Label success;
masm.branch32(Assembler::LessThanOrEqual, input, Imm32(r->upper()), &success);
masm.breakpoint();
@ -7566,7 +7569,7 @@ CodeGenerator::emitAssertRangeD(const Range *r, FloatRegister input, FloatRegist
// This code does not yet check r->canHaveFractionalPart(). This would require new
// assembler interfaces to make rounding instructions available.
if (!r->canBeInfiniteOrNaN()) {
if (!r->hasInt32Bounds() && !r->canBeInfiniteOrNaN() && r->exponent() < DoubleExponentBias) {
// Check the bounds implied by the maximum exponent.
Label exponentLoOk;
masm.loadConstantDouble(pow(2.0, r->exponent() + 1), temp);
@ -7581,6 +7584,27 @@ CodeGenerator::emitAssertRangeD(const Range *r, FloatRegister input, FloatRegist
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, input, temp, &exponentHiOk);
masm.breakpoint();
masm.bind(&exponentHiOk);
} else if (!r->hasInt32Bounds() && !r->canBeNaN()) {
// If we think the value can't be NaN, check that it isn't.
Label notnan;
masm.branchDouble(Assembler::DoubleOrdered, input, input, &notnan);
masm.breakpoint();
masm.bind(&notnan);
// If we think the value also can't be an infinity, check that it isn't.
if (!r->canBeInfiniteOrNaN()) {
Label notposinf;
masm.loadConstantDouble(PositiveInfinity(), temp);
masm.branchDouble(Assembler::DoubleLessThan, input, temp, &notposinf);
masm.breakpoint();
masm.bind(&notposinf);
Label notneginf;
masm.loadConstantDouble(NegativeInfinity(), temp);
masm.branchDouble(Assembler::DoubleGreaterThan, input, temp, &notneginf);
masm.breakpoint();
masm.bind(&notneginf);
}
}
return true;

View File

@ -674,9 +674,7 @@ Range::ursh(const Range *lhs, int32_t c)
// If the value is always non-negative or always negative, we can simply
// compute the correct range by shifting.
if ((lhs->lower_ >= 0 && lhs->hasInt32UpperBound()) ||
(lhs->upper_ < 0 && lhs->hasInt32LowerBound()))
{
if (lhs->isFiniteNonNegative() || lhs->isFiniteNegative()) {
return Range::NewUInt32Range(
uint32_t(lhs->lower_) >> shift,
uint32_t(lhs->upper_) >> shift);
@ -705,7 +703,7 @@ Range::rsh(const Range *lhs, const Range *rhs)
Range *
Range::ursh(const Range *lhs, const Range *rhs)
{
return Range::NewUInt32Range(0, (lhs->lower() >= 0 && lhs->hasInt32UpperBound()) ? lhs->upper() : UINT32_MAX);
return Range::NewUInt32Range(0, lhs->isFiniteNonNegative() ? lhs->upper() : UINT32_MAX);
}
Range *
@ -752,19 +750,10 @@ Range::max(const Range *lhs, const Range *rhs)
bool
Range::negativeZeroMul(const Range *lhs, const Range *rhs)
{
// Both values are positive
if (lhs->lower_ >= 0 && rhs->lower_ >= 0)
return false;
// Both values are negative (non zero)
if (lhs->upper_ < 0 && rhs->upper_ < 0)
return false;
// One operand is positive (non zero)
if (lhs->lower_ > 0 || rhs->lower_ > 0)
return false;
return true;
// The result can only be negative zero if both sides are finite and they
// have differing signs.
return (lhs->canBeFiniteNegative() && rhs->canBeFiniteNonNegative()) ||
(rhs->canBeFiniteNegative() && lhs->canBeFiniteNonNegative());
}
bool
@ -2202,23 +2191,25 @@ RangeAnalysis::truncate()
void
MInArray::collectRangeInfo()
{
needsNegativeIntCheck_ = !index()->range() || index()->range()->lower() < 0;
needsNegativeIntCheck_ = !index()->range() || !index()->range()->isFiniteNonNegative();
}
void
MLoadElementHole::collectRangeInfo()
{
needsNegativeIntCheck_ = !index()->range() || index()->range()->lower() < 0;
needsNegativeIntCheck_ = !index()->range() || !index()->range()->isFiniteNonNegative();
}
void
MMod::collectRangeInfo()
{
canBeNegativeDividend_ = !lhs()->range() || lhs()->range()->lower() < 0;
canBeNegativeDividend_ = !lhs()->range() || !lhs()->range()->isFiniteNonNegative();
}
void
MBoundsCheckLower::collectRangeInfo()
{
fallible_ = !index()->range() || index()->range()->lower() < minimum_;
fallible_ = !index()->range() ||
!index()->range()->hasInt32LowerBound() ||
index()->range()->lower() < minimum_;
}

View File

@ -367,6 +367,28 @@ class Range : public TempObject {
return upper_;
}
// Test whether all values in this range can are finite and negative.
bool isFiniteNegative() const {
return upper_ < 0 && !canBeInfiniteOrNaN();
}
// Test whether all values in this range can are finite and non-negative.
bool isFiniteNonNegative() const {
return lower_ >= 0 && !canBeInfiniteOrNaN();
}
// Test whether a value in this range can possibly be a finite
// negative value.
bool canBeFiniteNegative() const {
return lower_ < 0;
}
// Test whether a value in this range can possibly be a finite
// non-negative value.
bool canBeFiniteNonNegative() const {
return upper_ >= 0;
}
void setLower(int64_t x) {
setLowerInit(x);
rectifyExponent();