js/src/jit/RangeAnalysis.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef jit_RangeAnalysis_h
     8 #define jit_RangeAnalysis_h
    10 #include "mozilla/FloatingPoint.h"
    11 #include "mozilla/MathAlgorithms.h"
    13 #include "jit/IonAnalysis.h"
    14 #include "jit/MIR.h"
    16 // windows.h defines those, which messes with the definitions below.
    17 #undef min
    18 #undef max
    20 namespace js {
    21 namespace jit {
    23 class MBasicBlock;
    24 class MIRGraph;
    26 // An upper bound computed on the number of backedges a loop will take.
    27 // This count only includes backedges taken while running Ion code: for OSR
    28 // loops, this will exclude iterations that executed in the interpreter or in
    29 // baseline compiled code.
    30 struct LoopIterationBound : public TempObject
    31 {
    32     // Loop for which this bound applies.
    33     MBasicBlock *header;
    35     // Test from which this bound was derived. Code in the loop body which this
    36     // test dominates (will include the backedge) will execute at most 'bound'
    37     // times. Other code in the loop will execute at most '1 + Max(bound, 0)'
    38     // times.
    39     MTest *test;
    41     // Symbolic bound computed for the number of backedge executions.
    42     LinearSum sum;
    44     LoopIterationBound(MBasicBlock *header, MTest *test, LinearSum sum)
    45       : header(header), test(test), sum(sum)
    46     {
    47     }
    48 };
    50 // A symbolic upper or lower bound computed for a term.
    51 struct SymbolicBound : public TempObject
    52 {
    53   private:
    54     SymbolicBound(LoopIterationBound *loop, LinearSum sum)
    55       : loop(loop), sum(sum)
    56     {
    57     }
    59   public:
    60     // Any loop iteration bound from which this was derived.
    61     //
    62     // If non-nullptr, then 'sum' is only valid within the loop body, at
    63     // points dominated by the loop bound's test (see LoopIterationBound).
    64     //
    65     // If nullptr, then 'sum' is always valid.
    66     LoopIterationBound *loop;
    68     static SymbolicBound *New(TempAllocator &alloc, LoopIterationBound *loop, LinearSum sum) {
    69         return new(alloc) SymbolicBound(loop, sum);
    70     }
    72     // Computed symbolic bound, see above.
    73     LinearSum sum;
    75     void print(Sprinter &sp) const;
    76     void dump() const;
    77 };
    79 class RangeAnalysis
    80 {
    81   protected:
    82     bool blockDominates(MBasicBlock *b, MBasicBlock *b2);
    83     void replaceDominatedUsesWith(MDefinition *orig, MDefinition *dom,
    84                                   MBasicBlock *block);
    86   protected:
    87     MIRGenerator *mir;
    88     MIRGraph &graph_;
    90     TempAllocator &alloc() const;
    92   public:
    93     MOZ_CONSTEXPR RangeAnalysis(MIRGenerator *mir, MIRGraph &graph) :
    94         mir(mir), graph_(graph) {}
    95     bool addBetaNodes();
    96     bool analyze();
    97     bool addRangeAssertions();
    98     bool removeBetaNodes();
    99     bool prepareForUCE(bool *shouldRemoveDeadCode);
   100     bool truncate();
   102   private:
   103     bool analyzeLoop(MBasicBlock *header);
   104     LoopIterationBound *analyzeLoopIterationCount(MBasicBlock *header,
   105                                                   MTest *test, BranchDirection direction);
   106     void analyzeLoopPhi(MBasicBlock *header, LoopIterationBound *loopBound, MPhi *phi);
   107     bool tryHoistBoundsCheck(MBasicBlock *header, MBoundsCheck *ins);
   108     bool markBlocksInLoopBody(MBasicBlock *header, MBasicBlock *current);
   109 };
   111 class Range : public TempObject {
   112   public:
   113     // Int32 are signed. INT32_MAX is pow(2,31)-1 and INT32_MIN is -pow(2,31),
   114     // so the greatest exponent we need is 31.
   115     static const uint16_t MaxInt32Exponent = 31;
   117     // UInt32 are unsigned. UINT32_MAX is pow(2,32)-1, so it's the greatest
   118     // value that has an exponent of 31.
   119     static const uint16_t MaxUInt32Exponent = 31;
   121     // Maximal exponenent under which we have no precission loss on double
   122     // operations. Double has 52 bits of mantissa, so 2^52+1 cannot be
   123     // represented without loss.
   124     static const uint16_t MaxTruncatableExponent = mozilla::FloatingPoint<double>::ExponentShift;
   126     // Maximum exponent for finite values.
   127     static const uint16_t MaxFiniteExponent = mozilla::FloatingPoint<double>::ExponentBias;
   129     // An special exponent value representing all non-NaN values. This
   130     // includes finite values and the infinities.
   131     static const uint16_t IncludesInfinity = MaxFiniteExponent + 1;
   133     // An special exponent value representing all possible double-precision
   134     // values. This includes finite values, the infinities, and NaNs.
   135     static const uint16_t IncludesInfinityAndNaN = UINT16_MAX;
   137     // This range class uses int32_t ranges, but has several interfaces which
   138     // use int64_t, which either holds an int32_t value, or one of the following
   139     // special values which mean a value which is beyond the int32 range,
   140     // potentially including infinity or NaN. These special values are
   141     // guaranteed to compare greater, and less than, respectively, any int32_t
   142     // value.
   143     static const int64_t NoInt32UpperBound = int64_t(JSVAL_INT_MAX) + 1;
   144     static const int64_t NoInt32LowerBound = int64_t(JSVAL_INT_MIN) - 1;
   146   private:
   147     // Absolute ranges.
   148     //
   149     // We represent ranges where the endpoints can be in the set:
   150     // {-infty} U [INT_MIN, INT_MAX] U {infty}.  A bound of +/-
   151     // infty means that the value may have overflowed in that
   152     // direction. When computing the range of an integer
   153     // instruction, the ranges of the operands can be clamped to
   154     // [INT_MIN, INT_MAX], since if they had overflowed they would
   155     // no longer be integers. This is important for optimizations
   156     // and somewhat subtle.
   157     //
   158     // N.B.: All of the operations that compute new ranges based
   159     // on existing ranges will ignore the hasInt32*Bound_ flags of the
   160     // input ranges; that is, they implicitly clamp the ranges of
   161     // the inputs to [INT_MIN, INT_MAX]. Therefore, while our range might
   162     // be unbounded (and could overflow), when using this information to
   163     // propagate through other ranges, we disregard this fact; if that code
   164     // executes, then the overflow did not occur, so we may safely assume
   165     // that the range is [INT_MIN, INT_MAX] instead.
   166     //
   167     // To facilitate this trick, we maintain the invariants that:
   168     // 1) hasInt32LowerBound_ == false implies lower_ == JSVAL_INT_MIN
   169     // 2) hasInt32UpperBound_ == false implies upper_ == JSVAL_INT_MAX
   170     //
   171     // As a second and less precise range analysis, we represent the maximal
   172     // exponent taken by a value. The exponent is calculated by taking the
   173     // absolute value and looking at the position of the highest bit.  All
   174     // exponent computation have to be over-estimations of the actual result. On
   175     // the Int32 this over approximation is rectified.
   177     int32_t lower_;
   178     bool hasInt32LowerBound_;
   180     int32_t upper_;
   181     bool hasInt32UpperBound_;
   183     bool canHaveFractionalPart_;
   184     uint16_t max_exponent_;
   186     // Any symbolic lower or upper bound computed for this term.
   187     const SymbolicBound *symbolicLower_;
   188     const SymbolicBound *symbolicUpper_;
   190     // This function simply makes several JS_ASSERTs to verify the internal
   191     // consistency of this range.
   192     void assertInvariants() const {
   193         // Basic sanity :).
   194         JS_ASSERT(lower_ <= upper_);
   196         // When hasInt32LowerBound_ or hasInt32UpperBound_ are false, we set
   197         // lower_ and upper_ to these specific values as it simplifies the
   198         // implementation in some places.
   199         JS_ASSERT_IF(!hasInt32LowerBound_, lower_ == JSVAL_INT_MIN);
   200         JS_ASSERT_IF(!hasInt32UpperBound_, upper_ == JSVAL_INT_MAX);
   202         // max_exponent_ must be one of three possible things.
   203         JS_ASSERT(max_exponent_ <= MaxFiniteExponent ||
   204                   max_exponent_ == IncludesInfinity ||
   205                   max_exponent_ == IncludesInfinityAndNaN);
   207         // Forbid the max_exponent_ field from implying better bounds for
   208         // lower_/upper_ fields. We have to add 1 to the max_exponent_ when
   209         // canHaveFractionalPart_ is true in order to accomodate fractional
   210         // offsets. For example, 2147483647.9 is greater than INT32_MAX, so a
   211         // range containing that value will have hasInt32UpperBound_ set to
   212         // false, however that value also has exponent 30, which is strictly
   213         // less than MaxInt32Exponent. For another example, 1.9 has an exponent
   214         // of 0 but requires upper_ to be at least 2, which has exponent 1.
   215         JS_ASSERT_IF(!hasInt32LowerBound_ || !hasInt32UpperBound_,
   216                      max_exponent_ + canHaveFractionalPart_ >= MaxInt32Exponent);
   217         JS_ASSERT(max_exponent_ + canHaveFractionalPart_ >=
   218                   mozilla::FloorLog2(mozilla::Abs(upper_)));
   219         JS_ASSERT(max_exponent_ + canHaveFractionalPart_ >=
   220                   mozilla::FloorLog2(mozilla::Abs(lower_)));
   222         // The following are essentially static assertions, but FloorLog2 isn't
   223         // trivially suitable for constexpr :(.
   224         JS_ASSERT(mozilla::FloorLog2(JSVAL_INT_MIN) == MaxInt32Exponent);
   225         JS_ASSERT(mozilla::FloorLog2(JSVAL_INT_MAX) == 30);
   226         JS_ASSERT(mozilla::FloorLog2(UINT32_MAX) == MaxUInt32Exponent);
   227         JS_ASSERT(mozilla::FloorLog2(0) == 0);
   228     }
   230     // Set the lower_ and hasInt32LowerBound_ values.
   231     void setLowerInit(int64_t x) {
   232         if (x > JSVAL_INT_MAX) {
   233             lower_ = JSVAL_INT_MAX;
   234             hasInt32LowerBound_ = true;
   235         } else if (x < JSVAL_INT_MIN) {
   236             lower_ = JSVAL_INT_MIN;
   237             hasInt32LowerBound_ = false;
   238         } else {
   239             lower_ = int32_t(x);
   240             hasInt32LowerBound_ = true;
   241         }
   242     }
   243     // Set the upper_ and hasInt32UpperBound_ values.
   244     void setUpperInit(int64_t x) {
   245         if (x > JSVAL_INT_MAX) {
   246             upper_ = JSVAL_INT_MAX;
   247             hasInt32UpperBound_ = false;
   248         } else if (x < JSVAL_INT_MIN) {
   249             upper_ = JSVAL_INT_MIN;
   250             hasInt32UpperBound_ = true;
   251         } else {
   252             upper_ = int32_t(x);
   253             hasInt32UpperBound_ = true;
   254         }
   255     }
   257     // Compute the least exponent value that would be compatible with the
   258     // values of lower() and upper().
   259     //
   260     // Note:
   261     //     exponent of JSVAL_INT_MIN == 31
   262     //     exponent of JSVAL_INT_MAX == 30
   263     uint16_t exponentImpliedByInt32Bounds() const {
   264          // The number of bits needed to encode |max| is the power of 2 plus one.
   265          uint32_t max = Max(mozilla::Abs(lower()), mozilla::Abs(upper()));
   266          uint16_t result = mozilla::FloorLog2(max);
   267          JS_ASSERT(result == (max == 0 ? 0 : mozilla::ExponentComponent(double(max))));
   268          return result;
   269     }
   271     // When converting a range which contains fractional values to a range
   272     // containing only integers, the old max_exponent_ value may imply a better
   273     // lower and/or upper bound than was previously available, because they no
   274     // longer need to be conservative about fractional offsets and the ends of
   275     // the range.
   276     //
   277     // Given an exponent value and pointers to the lower and upper bound values,
   278     // this function refines the lower and upper bound values to the tighest
   279     // bound for integer values implied by the exponent.
   280     static void refineInt32BoundsByExponent(uint16_t e, int32_t *l, int32_t *h) {
   281        if (e < MaxInt32Exponent) {
   282            // pow(2, max_exponent_+1)-1 to compute a maximum absolute value.
   283            int32_t limit = (uint32_t(1) << (e + 1)) - 1;
   284            *h = Min(*h, limit);
   285            *l = Max(*l, -limit);
   286        }
   287     }
   289     // If the value of any of the fields implies a stronger possible value for
   290     // any other field, update that field to the stronger value. The range must
   291     // be completely valid before and it is guaranteed to be kept valid.
   292     void optimize() {
   293         assertInvariants();
   295         if (hasInt32Bounds()) {
   296             // Examine lower() and upper(), and if they imply a better exponent
   297             // bound than max_exponent_, set that value as the new
   298             // max_exponent_.
   299             uint16_t newExponent = exponentImpliedByInt32Bounds();
   300             if (newExponent < max_exponent_) {
   301                 max_exponent_ = newExponent;
   302                 assertInvariants();
   303             }
   305             // If we have a completely precise range, the value is an integer,
   306             // since we can only represent integers.
   307             if (canHaveFractionalPart_ && lower_ == upper_) {
   308                 canHaveFractionalPart_ = false;
   309                 assertInvariants();
   310             }
   311         }
   312     }
   314     // Set the range fields to the given raw values.
   315     void rawInitialize(int32_t l, bool lb, int32_t h, bool hb, bool f, uint16_t e) {
   316         lower_ = l;
   317         hasInt32LowerBound_ = lb;
   318         upper_ = h;
   319         hasInt32UpperBound_ = hb;
   320         canHaveFractionalPart_ = f;
   321         max_exponent_ = e;
   322         optimize();
   323     }
   325     // Construct a range from the given raw values.
   326     Range(int32_t l, bool lb, int32_t h, bool hb, bool f, uint16_t e)
   327       : symbolicLower_(nullptr),
   328         symbolicUpper_(nullptr)
   329      {
   330         rawInitialize(l, lb, h, hb, f, e);
   331      }
   333   public:
   334     Range()
   335       : symbolicLower_(nullptr),
   336         symbolicUpper_(nullptr)
   337     {
   338         setUnknown();
   339     }
   341     Range(int64_t l, int64_t h, bool f = false, uint16_t e = MaxInt32Exponent)
   342       : symbolicLower_(nullptr),
   343         symbolicUpper_(nullptr)
   344     {
   345         set(l, h, f, e);
   346     }
   348     Range(const Range &other)
   349       : lower_(other.lower_),
   350         hasInt32LowerBound_(other.hasInt32LowerBound_),
   351         upper_(other.upper_),
   352         hasInt32UpperBound_(other.hasInt32UpperBound_),
   353         canHaveFractionalPart_(other.canHaveFractionalPart_),
   354         max_exponent_(other.max_exponent_),
   355         symbolicLower_(nullptr),
   356         symbolicUpper_(nullptr)
   357     {
   358         assertInvariants();
   359     }
   361     // Construct a range from the given MDefinition. This differs from the
   362     // MDefinition's range() method in that it describes the range of values
   363     // *after* any bailout checks.
   364     Range(const MDefinition *def);
   366     static Range *NewInt32Range(TempAllocator &alloc, int32_t l, int32_t h) {
   367         return new(alloc) Range(l, h, false, MaxInt32Exponent);
   368     }
   370     static Range *NewUInt32Range(TempAllocator &alloc, uint32_t l, uint32_t h) {
   371         // For now, just pass them to the constructor as int64_t values.
   372         // They'll become unbounded if they're not in the int32_t range.
   373         return new(alloc) Range(l, h, false, MaxUInt32Exponent);
   374     }
   376     static Range *NewDoubleRange(TempAllocator &alloc, double l, double h) {
   377         if (mozilla::IsNaN(l) && mozilla::IsNaN(h))
   378             return nullptr;
   380         Range *r = new(alloc) Range();
   381         r->setDouble(l, h);
   382         return r;
   383     }
   385     void print(Sprinter &sp) const;
   386     void dump(FILE *fp) const;
   387     void dump() const;
   388     bool update(const Range *other);
   390     // Unlike the other operations, unionWith is an in-place
   391     // modification. This is to avoid a bunch of useless extra
   392     // copying when chaining together unions when handling Phi
   393     // nodes.
   394     void unionWith(const Range *other);
   395     static Range *intersect(TempAllocator &alloc, const Range *lhs, const Range *rhs,
   396                              bool *emptyRange);
   397     static Range *add(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   398     static Range *sub(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   399     static Range *mul(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   400     static Range *and_(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   401     static Range *or_(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   402     static Range *xor_(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   403     static Range *not_(TempAllocator &alloc, const Range *op);
   404     static Range *lsh(TempAllocator &alloc, const Range *lhs, int32_t c);
   405     static Range *rsh(TempAllocator &alloc, const Range *lhs, int32_t c);
   406     static Range *ursh(TempAllocator &alloc, const Range *lhs, int32_t c);
   407     static Range *lsh(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   408     static Range *rsh(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   409     static Range *ursh(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   410     static Range *abs(TempAllocator &alloc, const Range *op);
   411     static Range *min(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   412     static Range *max(TempAllocator &alloc, const Range *lhs, const Range *rhs);
   414     static bool negativeZeroMul(const Range *lhs, const Range *rhs);
   416     bool isUnknownInt32() const {
   417         return isInt32() && lower() == INT32_MIN && upper() == INT32_MAX;
   418     }
   420     bool isUnknown() const {
   421         return !hasInt32LowerBound_ &&
   422                !hasInt32UpperBound_ &&
   423                canHaveFractionalPart_ &&
   424                max_exponent_ == IncludesInfinityAndNaN;
   425     }
   427     bool hasInt32LowerBound() const {
   428         return hasInt32LowerBound_;
   429     }
   430     bool hasInt32UpperBound() const {
   431         return hasInt32UpperBound_;
   432     }
   434     // Test whether the value is known to be within [INT32_MIN,INT32_MAX].
   435     // Note that this does not necessarily mean the value is an integer.
   436     bool hasInt32Bounds() const {
   437         return hasInt32LowerBound() && hasInt32UpperBound();
   438     }
   440     // Test whether the value is known to be representable as an int32.
   441     bool isInt32() const {
   442         return hasInt32Bounds() && !canHaveFractionalPart();
   443     }
   445     // Test whether the given value is known to be either 0 or 1.
   446     bool isBoolean() const {
   447         return lower() >= 0 && upper() <= 1 && !canHaveFractionalPart();
   448     }
   450     bool canHaveRoundingErrors() const {
   451         return canHaveFractionalPart() || max_exponent_ >= MaxTruncatableExponent;
   452     }
   454     // Test whether the range contains zero.
   455     bool canBeZero() const {
   456         return lower_ <= 0 && upper_ >= 0;
   457     }
   459     // Test whether the range contains NaN values.
   460     bool canBeNaN() const {
   461         return max_exponent_ == IncludesInfinityAndNaN;
   462     }
   464     // Test whether the range contains infinities or NaN values.
   465     bool canBeInfiniteOrNaN() const {
   466         return max_exponent_ >= IncludesInfinity;
   467     }
   469     bool canHaveFractionalPart() const {
   470         return canHaveFractionalPart_;
   471     }
   473     uint16_t exponent() const {
   474         JS_ASSERT(!canBeInfiniteOrNaN());
   475         return max_exponent_;
   476     }
   478     uint16_t numBits() const {
   479         return exponent() + 1; // 2^0 -> 1
   480     }
   482     // Return the lower bound. Asserts that the value has an int32 bound.
   483     int32_t lower() const {
   484         JS_ASSERT(hasInt32LowerBound());
   485         return lower_;
   486     }
   488     // Return the upper bound. Asserts that the value has an int32 bound.
   489     int32_t upper() const {
   490         JS_ASSERT(hasInt32UpperBound());
   491         return upper_;
   492     }
   494     // Test whether all values in this range can are finite and negative.
   495     bool isFiniteNegative() const {
   496         return upper_ < 0 && !canBeInfiniteOrNaN();
   497     }
   499     // Test whether all values in this range can are finite and non-negative.
   500     bool isFiniteNonNegative() const {
   501         return lower_ >= 0 && !canBeInfiniteOrNaN();
   502     }
   504     // Test whether a value in this range can possibly be a finite
   505     // negative value.
   506     bool canBeFiniteNegative() const {
   507         return lower_ < 0;
   508     }
   510     // Test whether a value in this range can possibly be a finite
   511     // non-negative value.
   512     bool canBeFiniteNonNegative() const {
   513         return upper_ >= 0;
   514     }
   516     // Set this range to have a lower bound not less than x.
   517     void refineLower(int32_t x) {
   518         assertInvariants();
   519         hasInt32LowerBound_ = true;
   520         lower_ = Max(lower_, x);
   521         optimize();
   522     }
   524     // Set this range to have an upper bound not greater than x.
   525     void refineUpper(int32_t x) {
   526         assertInvariants();
   527         hasInt32UpperBound_ = true;
   528         upper_ = Min(upper_, x);
   529         optimize();
   530     }
   532     void setInt32(int32_t l, int32_t h) {
   533         hasInt32LowerBound_ = true;
   534         hasInt32UpperBound_ = true;
   535         lower_ = l;
   536         upper_ = h;
   537         canHaveFractionalPart_ = false;
   538         max_exponent_ = exponentImpliedByInt32Bounds();
   539         assertInvariants();
   540     }
   542     void setDouble(double l, double h);
   544     void setUnknown() {
   545         set(NoInt32LowerBound, NoInt32UpperBound, true, IncludesInfinityAndNaN);
   546         JS_ASSERT(isUnknown());
   547     }
   549     void set(int64_t l, int64_t h, bool f, uint16_t e) {
   550         max_exponent_ = e;
   551         canHaveFractionalPart_ = f;
   552         setLowerInit(l);
   553         setUpperInit(h);
   554         optimize();
   555     }
   557     // Make the lower end of this range at least INT32_MIN, and make
   558     // the upper end of this range at most INT32_MAX.
   559     void clampToInt32();
   561     // If this range exceeds int32_t range, at either or both ends, change
   562     // it to int32_t range.  Otherwise do nothing.
   563     void wrapAroundToInt32();
   565     // If this range exceeds [0, 32) range, at either or both ends, change
   566     // it to the [0, 32) range.  Otherwise do nothing.
   567     void wrapAroundToShiftCount();
   569     // If this range exceeds [0, 1] range, at either or both ends, change
   570     // it to the [0, 1] range.  Otherwise do nothing.
   571     void wrapAroundToBoolean();
   573     const SymbolicBound *symbolicLower() const {
   574         return symbolicLower_;
   575     }
   576     const SymbolicBound *symbolicUpper() const {
   577         return symbolicUpper_;
   578     }
   580     void setSymbolicLower(SymbolicBound *bound) {
   581         symbolicLower_ = bound;
   582     }
   583     void setSymbolicUpper(SymbolicBound *bound) {
   584         symbolicUpper_ = bound;
   585     }
   586 };
   588 } // namespace jit
   589 } // namespace js
   591 #endif /* jit_RangeAnalysis_h */

mercurial