From df22f16de715a79c510767bdabf9bae83642354f Mon Sep 17 00:00:00 2001 From: Marty Rosenberg Date: Tue, 2 Oct 2012 04:34:28 -0400 Subject: [PATCH] Add a bunch of features to range analysis to make it optimize more. (bug 765119, r=jandem) --- js/src/ion/JSONSpewer.cpp | 3 ++- js/src/ion/MIR.h | 27 +++++++++++++++++++++---- js/src/ion/RangeAnalysis.cpp | 30 ++++++++++++++++------------ js/src/ion/RangeAnalysis.h | 4 ++-- js/src/ion/arm/CodeGenerator-arm.cpp | 6 ++---- 5 files changed, 46 insertions(+), 24 deletions(-) diff --git a/js/src/ion/JSONSpewer.cpp b/js/src/ion/JSONSpewer.cpp index f9e8c940494..09de5d982eb 100644 --- a/js/src/ion/JSONSpewer.cpp +++ b/js/src/ion/JSONSpewer.cpp @@ -255,7 +255,8 @@ JSONSpewer::spewMDef(MDefinition *def) integerValue(use.def()->id()); endList(); - stringProperty("type", StringFromMIRType(def->type())); + stringProperty("type", "%s : [%d, %d]", StringFromMIRType(def->type()), + def->range()->lower(), def->range()->upper()); if (def->isInstruction()) { if (MResumePoint *rp = def->toInstruction()->resumePoint()) diff --git a/js/src/ion/MIR.h b/js/src/ion/MIR.h index 430e7b66619..3c5e5b24ee2 100644 --- a/js/src/ion/MIR.h +++ b/js/src/ion/MIR.h @@ -61,6 +61,8 @@ class MUse; class MIRGraph; class MResumePoint; +static inline bool isOSRLikeValue (MDefinition *def); + // Represents a use of a node. class MUse : public TempObject, public InlineForwardListNode { @@ -1919,6 +1921,12 @@ class MBitAnd : public MBinaryBitwiseInstruction MDefinition *foldIfEqual() { return getOperand(0); // x & x => x; } + bool recomputeRange() { + Range *left = getOperand(0)->range(); + Range *right = getOperand(1)->range(); + return range()->update(Range::and_(left, right)); + } + }; class MBitOr : public MBinaryBitwiseInstruction @@ -2733,16 +2741,17 @@ class MPhi : public MDefinition, public InlineForwardListNode AliasSet getAliasSet() const { return AliasSet::None(); } - bool recomputeRange() { if (type() != MIRType_Int32) return false; Range r; r.update(getOperand(0)->range()); - - for (size_t i = 0; i < numOperands(); i++) - r.unionWith(getOperand(i)->range()); + JS_ASSERT(getOperand(0)->op() != MDefinition::Op_OsrValue); + for (size_t i = 0; i < numOperands(); i++) { + if (!isOSRLikeValue(getOperand(i))) + r.unionWith(getOperand(i)->range(), true); + } return range()->update(&r); } @@ -5573,6 +5582,16 @@ void MNode::initOperand(size_t index, MDefinition *ins) setOperand(index, ins); ins->addUse(this, index); } +static inline bool isOSRLikeValue (MDefinition *def) { + if (def->isOsrValue()) + return true; + + if (def->isUnbox()) + if (def->getOperand(0)->isOsrValue()) + return true; + + return false; +} typedef Vector MDefinitionVector; diff --git a/js/src/ion/RangeAnalysis.cpp b/js/src/ion/RangeAnalysis.cpp index 0ea252cd5d5..51c3a6f3860 100644 --- a/js/src/ion/RangeAnalysis.cpp +++ b/js/src/ion/RangeAnalysis.cpp @@ -278,11 +278,11 @@ Range::intersect(const Range *lhs, const Range *rhs) } void -Range::unionWith(const Range *other) +Range::unionWith(const Range *other, bool useNarrowing) { setLower(Min(lower_, other->lower_)); - setUpper(Max(upper_, other->upper_)); lower_infinite_ |= other->lower_infinite_; + setUpper(Max(upper_, other->upper_)); upper_infinite_ |= other->upper_infinite_; } @@ -304,7 +304,20 @@ Range::sub(const Range *lhs, const Range *rhs) return ret; } +Range +Range::and_(const Range *lhs, const Range *rhs) +{ + uint64_t lower = 0; + // If both numbers can be negative, issues can be had. + if (lhs->lower_ < 0 && rhs->lower_ < 0) + lower = INT_MIN; + uint64_t upper = lhs->upper_; + if (rhs->upper_ < lhs->upper_) + upper = rhs->upper_; + Range ret(lower, upper); + return ret; +} Range Range::mul(const Range *lhs, const Range *rhs) { @@ -346,7 +359,6 @@ Range::update(const Range *other) lower_infinite_ != other->lower_infinite_ || upper_ != other->upper_ || upper_infinite_ != other->upper_infinite_; - if (changed) { lower_ = other->lower_; lower_infinite_ = other->lower_infinite_; @@ -386,20 +398,13 @@ RangeAnalysis::analyze() for (MDefinitionIterator iter(*block); iter; iter++) { MDefinition *def = *iter; - if (!def->isPhi() && !def->isBeta()) - continue; AddToWorklist(worklist, def); } } size_t iters = 0; -#define MAX_ITERS 4096 - // XXX: hack: range analysis iloops on jit-test/tests/basic/fannkuch.js - // To circumvent this and land the pass, we just run for a fixed number of - // iterations. - // - // (Bug 765119) - while (!worklist.empty() /* && iters < MAX_ITERS*/) { + + while (!worklist.empty()) { MDefinition *def = PopFromWorklist(worklist); IonSpew(IonSpew_Range, "recomputing range on %d", def->id()); SpewRange(def); @@ -417,7 +422,6 @@ RangeAnalysis::analyze() for(size_t i = 0; i < worklist.length(); i++) worklist[i]->setNotInWorklist(); -#undef MAX_ITERS #ifdef DEBUG for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) { diff --git a/js/src/ion/RangeAnalysis.h b/js/src/ion/RangeAnalysis.h index aa70452dd88..a5ee4b2fc06 100644 --- a/js/src/ion/RangeAnalysis.h +++ b/js/src/ion/RangeAnalysis.h @@ -106,13 +106,13 @@ class Range { // modification. This is to avoid a bunch of useless extra // copying when chaining together unions when handling Phi // nodes. - void unionWith(const Range *other); + void unionWith(const Range *other, bool useNarrowing = false); static Range intersect(const Range *lhs, const Range *rhs); static Range add(const Range *lhs, const Range *rhs); static Range sub(const Range *lhs, const Range *rhs); static Range mul(const Range *lhs, const Range *rhs); - + static Range and_(const Range *lhs, const Range *rhs); static Range shl(const Range *lhs, int32 c); static Range shr(const Range *lhs, int32 c); diff --git a/js/src/ion/arm/CodeGenerator-arm.cpp b/js/src/ion/arm/CodeGenerator-arm.cpp index 8c63c411366..ab613932083 100644 --- a/js/src/ion/arm/CodeGenerator-arm.cpp +++ b/js/src/ion/arm/CodeGenerator-arm.cpp @@ -467,12 +467,10 @@ CodeGeneratorARM::visitMulI(LMulI *ins) Assembler::Condition c = Assembler::Overflow; //masm.imull(ToOperand(rhs), ToRegister(lhs)); - if (mul->canOverflow()) { + if (mul->canOverflow()) c = masm.ma_check_mul(ToRegister(lhs), ToRegister(rhs), ToRegister(dest), c); - } else { + else masm.ma_mul(ToRegister(lhs), ToRegister(rhs), ToRegister(dest)); - } - // Bailout on overflow if (mul->canOverflow() && !bailoutIf(c, ins->snapshot()))