tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RangeAnalysis.h (25473B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
      2 * vim: set ts=8 sts=2 et sw=2 tw=80:
      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/. */
      6 
      7 #ifndef jit_RangeAnalysis_h
      8 #define jit_RangeAnalysis_h
      9 
     10 #include "mozilla/Assertions.h"
     11 #include "mozilla/Attributes.h"
     12 #include "mozilla/DebugOnly.h"
     13 #include "mozilla/FloatingPoint.h"
     14 #include "mozilla/MathAlgorithms.h"
     15 
     16 #include <algorithm>
     17 #include <stdint.h>
     18 
     19 #include "jit/IonAnalysis.h"
     20 #include "jit/IonTypes.h"
     21 #include "jit/JitAllocPolicy.h"
     22 #include "js/AllocPolicy.h"
     23 #include "js/Value.h"
     24 #include "js/Vector.h"
     25 
     26 namespace js {
     27 
     28 class JS_PUBLIC_API GenericPrinter;
     29 
     30 namespace jit {
     31 
     32 class MBasicBlock;
     33 class MBinaryBitwiseInstruction;
     34 class MBoundsCheck;
     35 class MDefinition;
     36 class MIRGenerator;
     37 class MIRGraph;
     38 class MPhi;
     39 class MTest;
     40 
     41 enum class TruncateKind;
     42 
     43 // An upper bound computed on the number of backedges a loop will take.
     44 // This count only includes backedges taken while running Ion code: for OSR
     45 // loops, this will exclude iterations that executed in the interpreter or in
     46 // baseline compiled code.
     47 struct LoopIterationBound : public TempObject {
     48  // Test from which this bound was derived; after executing exactly 'bound'
     49  // times this test will exit the loop. Code in the loop body which this
     50  // test dominates (will include the backedge) will execute at most 'bound'
     51  // times. Other code in the loop will execute at most '1 + Max(bound, 0)'
     52  // times.
     53  const MTest* test;
     54 
     55  // Symbolic bound computed for the number of backedge executions. The terms
     56  // in this bound are all loop invariant.
     57  LinearSum boundSum;
     58 
     59  LoopIterationBound(const MTest* test, const LinearSum& boundSum)
     60      : test(test), boundSum(boundSum) {}
     61 };
     62 
     63 using LoopIterationBoundVector =
     64    Vector<LoopIterationBound*, 0, SystemAllocPolicy>;
     65 
     66 // A symbolic upper or lower bound computed for a term.
     67 struct SymbolicBound : public TempObject {
     68 private:
     69  SymbolicBound(const LoopIterationBound* loop, const LinearSum& sum)
     70      : loop(loop), sum(sum) {}
     71 
     72 public:
     73  // Any loop iteration bound from which this was derived.
     74  //
     75  // If non-nullptr, then 'sum' is only valid within the loop body, at
     76  // points dominated by the loop bound's test (see LoopIterationBound).
     77  //
     78  // If nullptr, then 'sum' is always valid.
     79  const LoopIterationBound* loop;
     80 
     81  static SymbolicBound* New(TempAllocator& alloc,
     82                            const LoopIterationBound* loop,
     83                            const LinearSum& sum) {
     84    return new (alloc) SymbolicBound(loop, sum);
     85  }
     86 
     87  // Computed symbolic bound, see above.
     88  LinearSum sum;
     89 
     90  void dump(GenericPrinter& out) const;
     91  void dump() const;
     92 };
     93 
     94 class RangeAnalysis {
     95  const MIRGenerator* mir;
     96  MIRGraph& graph_;
     97  Vector<MBinaryBitwiseInstruction*, 16, SystemAllocPolicy> bitops;
     98 
     99  TempAllocator& alloc() const;
    100 
    101 public:
    102  RangeAnalysis(const MIRGenerator* mir, MIRGraph& graph)
    103      : mir(mir), graph_(graph) {}
    104  [[nodiscard]] bool addBetaNodes();
    105  [[nodiscard]] bool analyze();
    106  [[nodiscard]] bool addRangeAssertions();
    107  [[nodiscard]] bool removeBetaNodes();
    108  [[nodiscard]] bool prepareForUCE(bool* shouldRemoveDeadCode);
    109  [[nodiscard]] bool tryRemovingGuards();
    110  [[nodiscard]] bool truncate();
    111  [[nodiscard]] bool removeUnnecessaryBitops();
    112 
    113 private:
    114  bool canTruncate(const MDefinition* def, TruncateKind kind) const;
    115  void adjustTruncatedInputs(MDefinition* def);
    116 
    117  // Any iteration bounds discovered for loops in the graph.
    118  LoopIterationBoundVector loopIterationBounds;
    119 
    120 private:
    121  [[nodiscard]] bool analyzeLoop(const MBasicBlock* header);
    122  LoopIterationBound* analyzeLoopIterationCount(const MBasicBlock* header,
    123                                                const MTest* test,
    124                                                BranchDirection direction);
    125  void analyzeLoopPhi(const LoopIterationBound* loopBound, MPhi* phi);
    126  [[nodiscard]] bool tryHoistBoundsCheck(const MBasicBlock* header,
    127                                         const MBoundsCheck* ins);
    128 };
    129 
    130 class Range : public TempObject {
    131 public:
    132  // Int32 are signed. INT32_MAX is pow(2,31)-1 and INT32_MIN is -pow(2,31),
    133  // so the greatest exponent we need is 31.
    134  static const uint16_t MaxInt32Exponent = 31;
    135 
    136  // UInt32 are unsigned. UINT32_MAX is pow(2,32)-1, so it's the greatest
    137  // value that has an exponent of 31.
    138  static const uint16_t MaxUInt32Exponent = 31;
    139 
    140  // Maximal exponenent under which we have no precission loss on double
    141  // operations. Double has 52 bits of mantissa, so 2^52+1 cannot be
    142  // represented without loss.
    143  static const uint16_t MaxTruncatableExponent =
    144      mozilla::FloatingPoint<double>::kExponentShift;
    145 
    146  // Maximum exponent for finite values.
    147  static const uint16_t MaxFiniteExponent =
    148      mozilla::FloatingPoint<double>::kExponentBias;
    149 
    150  // An special exponent value representing all non-NaN values. This
    151  // includes finite values and the infinities.
    152  static const uint16_t IncludesInfinity = MaxFiniteExponent + 1;
    153 
    154  // An special exponent value representing all possible double-precision
    155  // values. This includes finite values, the infinities, and NaNs.
    156  static const uint16_t IncludesInfinityAndNaN = UINT16_MAX;
    157 
    158  // This range class uses int32_t ranges, but has several interfaces which
    159  // use int64_t, which either holds an int32_t value, or one of the following
    160  // special values which mean a value which is beyond the int32 range,
    161  // potentially including infinity or NaN. These special values are
    162  // guaranteed to compare greater, and less than, respectively, any int32_t
    163  // value.
    164  static const int64_t NoInt32UpperBound = int64_t(JSVAL_INT_MAX) + 1;
    165  static const int64_t NoInt32LowerBound = int64_t(JSVAL_INT_MIN) - 1;
    166 
    167  enum FractionalPartFlag : bool {
    168    ExcludesFractionalParts = false,
    169    IncludesFractionalParts = true
    170  };
    171  enum NegativeZeroFlag : bool {
    172    ExcludesNegativeZero = false,
    173    IncludesNegativeZero = true
    174  };
    175 
    176 private:
    177  // Absolute ranges.
    178  //
    179  // We represent ranges where the endpoints can be in the set:
    180  // {-infty} U [INT_MIN, INT_MAX] U {infty}.  A bound of +/-
    181  // infty means that the value may have overflowed in that
    182  // direction. When computing the range of an integer
    183  // instruction, the ranges of the operands can be clamped to
    184  // [INT_MIN, INT_MAX], since if they had overflowed they would
    185  // no longer be integers. This is important for optimizations
    186  // and somewhat subtle.
    187  //
    188  // N.B.: All of the operations that compute new ranges based
    189  // on existing ranges will ignore the hasInt32*Bound_ flags of the
    190  // input ranges; that is, they implicitly clamp the ranges of
    191  // the inputs to [INT_MIN, INT_MAX]. Therefore, while our range might
    192  // be unbounded (and could overflow), when using this information to
    193  // propagate through other ranges, we disregard this fact; if that code
    194  // executes, then the overflow did not occur, so we may safely assume
    195  // that the range is [INT_MIN, INT_MAX] instead.
    196  //
    197  // To facilitate this trick, we maintain the invariants that:
    198  // 1) hasInt32LowerBound_ == false implies lower_ == JSVAL_INT_MIN
    199  // 2) hasInt32UpperBound_ == false implies upper_ == JSVAL_INT_MAX
    200  //
    201  // As a second and less precise range analysis, we represent the maximal
    202  // exponent taken by a value. The exponent is calculated by taking the
    203  // absolute value and looking at the position of the highest bit.  All
    204  // exponent computation have to be over-estimations of the actual result. On
    205  // the Int32 this over approximation is rectified.
    206 
    207  MOZ_INIT_OUTSIDE_CTOR int32_t lower_;
    208  MOZ_INIT_OUTSIDE_CTOR int32_t upper_;
    209 
    210  MOZ_INIT_OUTSIDE_CTOR bool hasInt32LowerBound_;
    211  MOZ_INIT_OUTSIDE_CTOR bool hasInt32UpperBound_;
    212 
    213  MOZ_INIT_OUTSIDE_CTOR FractionalPartFlag canHaveFractionalPart_ : 1;
    214  MOZ_INIT_OUTSIDE_CTOR NegativeZeroFlag canBeNegativeZero_ : 1;
    215  MOZ_INIT_OUTSIDE_CTOR uint16_t max_exponent_;
    216 
    217  // Any symbolic lower or upper bound computed for this term.
    218  const SymbolicBound* symbolicLower_;
    219  const SymbolicBound* symbolicUpper_;
    220 
    221  // This function simply makes several MOZ_ASSERTs to verify the internal
    222  // consistency of this range.
    223  void assertInvariants() const {
    224    // Basic sanity :).
    225    MOZ_ASSERT(lower_ <= upper_);
    226 
    227    // When hasInt32LowerBound_ or hasInt32UpperBound_ are false, we set
    228    // lower_ and upper_ to these specific values as it simplifies the
    229    // implementation in some places.
    230    MOZ_ASSERT_IF(!hasInt32LowerBound_, lower_ == JSVAL_INT_MIN);
    231    MOZ_ASSERT_IF(!hasInt32UpperBound_, upper_ == JSVAL_INT_MAX);
    232 
    233    // max_exponent_ must be one of three possible things.
    234    MOZ_ASSERT(max_exponent_ <= MaxFiniteExponent ||
    235               max_exponent_ == IncludesInfinity ||
    236               max_exponent_ == IncludesInfinityAndNaN);
    237 
    238    // Forbid the max_exponent_ field from implying better bounds for
    239    // lower_/upper_ fields. We have to add 1 to the max_exponent_ when
    240    // canHaveFractionalPart_ is true in order to accomodate
    241    // fractional offsets. For example, 2147483647.9 is greater than
    242    // INT32_MAX, so a range containing that value will have
    243    // hasInt32UpperBound_ set to false, however that value also has
    244    // exponent 30, which is strictly less than MaxInt32Exponent. For
    245    // another example, 1.9 has an exponent of 0 but requires upper_ to be
    246    // at least 2, which has exponent 1.
    247    mozilla::DebugOnly<uint32_t> adjustedExponent =
    248        max_exponent_ + (canHaveFractionalPart_ ? 1 : 0);
    249    MOZ_ASSERT_IF(!hasInt32LowerBound_ || !hasInt32UpperBound_,
    250                  adjustedExponent >= MaxInt32Exponent);
    251    MOZ_ASSERT(adjustedExponent >= mozilla::FloorLog2(mozilla::Abs(upper_)));
    252    MOZ_ASSERT(adjustedExponent >= mozilla::FloorLog2(mozilla::Abs(lower_)));
    253 
    254    // The following are essentially static assertions, but FloorLog2 isn't
    255    // trivially suitable for constexpr :(.
    256    MOZ_ASSERT(mozilla::FloorLog2(JSVAL_INT_MIN) == MaxInt32Exponent);
    257    MOZ_ASSERT(mozilla::FloorLog2(JSVAL_INT_MAX) == 30);
    258    MOZ_ASSERT(mozilla::FloorLog2(UINT32_MAX) == MaxUInt32Exponent);
    259    MOZ_ASSERT(mozilla::FloorLog2(0) == 0);
    260  }
    261 
    262  // Set the lower_ and hasInt32LowerBound_ values.
    263  void setLowerInit(int64_t x) {
    264    if (x > JSVAL_INT_MAX) {
    265      lower_ = JSVAL_INT_MAX;
    266      hasInt32LowerBound_ = true;
    267    } else if (x < JSVAL_INT_MIN) {
    268      lower_ = JSVAL_INT_MIN;
    269      hasInt32LowerBound_ = false;
    270    } else {
    271      lower_ = int32_t(x);
    272      hasInt32LowerBound_ = true;
    273    }
    274  }
    275  // Set the upper_ and hasInt32UpperBound_ values.
    276  void setUpperInit(int64_t x) {
    277    if (x > JSVAL_INT_MAX) {
    278      upper_ = JSVAL_INT_MAX;
    279      hasInt32UpperBound_ = false;
    280    } else if (x < JSVAL_INT_MIN) {
    281      upper_ = JSVAL_INT_MIN;
    282      hasInt32UpperBound_ = true;
    283    } else {
    284      upper_ = int32_t(x);
    285      hasInt32UpperBound_ = true;
    286    }
    287  }
    288 
    289  // Compute the least exponent value that would be compatible with the
    290  // values of lower() and upper().
    291  //
    292  // Note:
    293  //     exponent of JSVAL_INT_MIN == 31
    294  //     exponent of JSVAL_INT_MAX == 30
    295  uint16_t exponentImpliedByInt32Bounds() const {
    296    // The number of bits needed to encode |max| is the power of 2 plus one.
    297    uint32_t max = std::max(mozilla::Abs(lower()), mozilla::Abs(upper()));
    298    uint16_t result = mozilla::FloorLog2(max);
    299    MOZ_ASSERT(result ==
    300               (max == 0 ? 0 : mozilla::ExponentComponent(double(max))));
    301    return result;
    302  }
    303 
    304  // When converting a range which contains fractional values to a range
    305  // containing only integers, the old max_exponent_ value may imply a better
    306  // lower and/or upper bound than was previously available, because they no
    307  // longer need to be conservative about fractional offsets and the ends of
    308  // the range.
    309  //
    310  // Given an exponent value and pointers to the lower and upper bound values,
    311  // this function refines the lower and upper bound values to the tighest
    312  // bound for integer values implied by the exponent.
    313  static void refineInt32BoundsByExponent(uint16_t e, int32_t* l, bool* lb,
    314                                          int32_t* h, bool* hb) {
    315    if (e < MaxInt32Exponent) {
    316      // pow(2, max_exponent_+1)-1 to compute a maximum absolute value.
    317      int32_t limit = (uint32_t(1) << (e + 1)) - 1;
    318      *h = std::min(*h, limit);
    319      *l = std::max(*l, -limit);
    320      *hb = true;
    321      *lb = true;
    322    }
    323  }
    324 
    325  // If the value of any of the fields implies a stronger possible value for
    326  // any other field, update that field to the stronger value. The range must
    327  // be completely valid before and it is guaranteed to be kept valid.
    328  void optimize() {
    329    assertInvariants();
    330 
    331    if (hasInt32Bounds()) {
    332      // Examine lower() and upper(), and if they imply a better exponent
    333      // bound than max_exponent_, set that value as the new
    334      // max_exponent_.
    335      uint16_t newExponent = exponentImpliedByInt32Bounds();
    336      if (newExponent < max_exponent_) {
    337        max_exponent_ = newExponent;
    338        assertInvariants();
    339      }
    340 
    341      // If we have a completely precise range, the value is an integer,
    342      // since we can only represent integers.
    343      if (canHaveFractionalPart_ && lower_ == upper_) {
    344        canHaveFractionalPart_ = ExcludesFractionalParts;
    345        assertInvariants();
    346      }
    347    }
    348 
    349    // If the range doesn't include zero, it doesn't include negative zero.
    350    if (canBeNegativeZero_ && !canBeZero()) {
    351      canBeNegativeZero_ = ExcludesNegativeZero;
    352      assertInvariants();
    353    }
    354  }
    355 
    356  // Set the range fields to the given raw values.
    357  void rawInitialize(int32_t l, bool lb, int32_t h, bool hb,
    358                     FractionalPartFlag canHaveFractionalPart,
    359                     NegativeZeroFlag canBeNegativeZero, uint16_t e) {
    360    lower_ = l;
    361    upper_ = h;
    362    hasInt32LowerBound_ = lb;
    363    hasInt32UpperBound_ = hb;
    364    canHaveFractionalPart_ = canHaveFractionalPart;
    365    canBeNegativeZero_ = canBeNegativeZero;
    366    max_exponent_ = e;
    367    optimize();
    368  }
    369 
    370  // Construct a range from the given raw values.
    371  Range(int32_t l, bool lb, int32_t h, bool hb,
    372        FractionalPartFlag canHaveFractionalPart,
    373        NegativeZeroFlag canBeNegativeZero, uint16_t e)
    374      : symbolicLower_(nullptr), symbolicUpper_(nullptr) {
    375    rawInitialize(l, lb, h, hb, canHaveFractionalPart, canBeNegativeZero, e);
    376  }
    377 
    378 public:
    379  Range() : symbolicLower_(nullptr), symbolicUpper_(nullptr) { setUnknown(); }
    380 
    381  Range(int64_t l, int64_t h, FractionalPartFlag canHaveFractionalPart,
    382        NegativeZeroFlag canBeNegativeZero, uint16_t e)
    383      : symbolicLower_(nullptr), symbolicUpper_(nullptr) {
    384    set(l, h, canHaveFractionalPart, canBeNegativeZero, e);
    385  }
    386 
    387  Range(const Range& other)
    388      : lower_(other.lower_),
    389        upper_(other.upper_),
    390        hasInt32LowerBound_(other.hasInt32LowerBound_),
    391        hasInt32UpperBound_(other.hasInt32UpperBound_),
    392        canHaveFractionalPart_(other.canHaveFractionalPart_),
    393        canBeNegativeZero_(other.canBeNegativeZero_),
    394        max_exponent_(other.max_exponent_),
    395        symbolicLower_(nullptr),
    396        symbolicUpper_(nullptr) {
    397    assertInvariants();
    398  }
    399 
    400  // Construct a range from the given MDefinition. This differs from the
    401  // MDefinition's range() method in that it describes the range of values
    402  // *after* any bailout checks.
    403  explicit Range(const MDefinition* def);
    404 
    405  static Range* NewInt32Range(TempAllocator& alloc, int32_t l, int32_t h) {
    406    return new (alloc) Range(l, h, ExcludesFractionalParts,
    407                             ExcludesNegativeZero, MaxInt32Exponent);
    408  }
    409 
    410  // Construct an int32 range containing just i. This is just a convenience
    411  // wrapper around NewInt32Range.
    412  static Range* NewInt32SingletonRange(TempAllocator& alloc, int32_t i) {
    413    return NewInt32Range(alloc, i, i);
    414  }
    415 
    416  static Range* NewUInt32Range(TempAllocator& alloc, uint32_t l, uint32_t h) {
    417    // For now, just pass them to the constructor as int64_t values.
    418    // They'll become unbounded if they're not in the int32_t range.
    419    return new (alloc) Range(l, h, ExcludesFractionalParts,
    420                             ExcludesNegativeZero, MaxUInt32Exponent);
    421  }
    422 
    423  // Construct a range containing values >= l and <= h. Note that this
    424  // function treats negative zero as equal to zero, as >= and <= do. If the
    425  // range includes zero, it is assumed to include negative zero too.
    426  static Range* NewDoubleRange(TempAllocator& alloc, double l, double h) {
    427    if (std::isnan(l) && std::isnan(h)) {
    428      return nullptr;
    429    }
    430 
    431    Range* r = new (alloc) Range();
    432    r->setDouble(l, h);
    433    return r;
    434  }
    435 
    436  // Construct the strictest possible range containing d, or null if d is NaN.
    437  // This function treats negative zero as distinct from zero, since this
    438  // makes the strictest possible range containin zero a range which
    439  // contains one value rather than two.
    440  static Range* NewDoubleSingletonRange(TempAllocator& alloc, double d) {
    441    if (std::isnan(d)) {
    442      return nullptr;
    443    }
    444 
    445    Range* r = new (alloc) Range();
    446    r->setDoubleSingleton(d);
    447    return r;
    448  }
    449 
    450  void dump(GenericPrinter& out) const;
    451  void dump() const;
    452  [[nodiscard]] bool update(const Range* other);
    453 
    454  // Unlike the other operations, unionWith is an in-place
    455  // modification. This is to avoid a bunch of useless extra
    456  // copying when chaining together unions when handling Phi
    457  // nodes.
    458  void unionWith(const Range* other);
    459  static Range* intersect(TempAllocator& alloc, const Range* lhs,
    460                          const Range* rhs, bool* emptyRange);
    461  static Range* add(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    462  static Range* sub(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    463  static Range* mul(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    464  static Range* and_(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    465  static Range* or_(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    466  static Range* xor_(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    467  static Range* not_(TempAllocator& alloc, const Range* op);
    468  static Range* lsh(TempAllocator& alloc, const Range* lhs, int32_t c);
    469  static Range* rsh(TempAllocator& alloc, const Range* lhs, int32_t c);
    470  static Range* ursh(TempAllocator& alloc, const Range* lhs, int32_t c);
    471  static Range* lsh(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    472  static Range* rsh(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    473  static Range* ursh(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    474  static Range* abs(TempAllocator& alloc, const Range* op);
    475  static Range* min(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    476  static Range* max(TempAllocator& alloc, const Range* lhs, const Range* rhs);
    477  static Range* floor(TempAllocator& alloc, const Range* op);
    478  static Range* ceil(TempAllocator& alloc, const Range* op);
    479  static Range* sign(TempAllocator& alloc, const Range* op);
    480  static Range* NaNToZero(TempAllocator& alloc, const Range* op);
    481 
    482  [[nodiscard]] static bool negativeZeroMul(const Range* lhs, const Range* rhs);
    483 
    484  bool isUnknownInt32() const {
    485    return isInt32() && lower() == INT32_MIN && upper() == INT32_MAX;
    486  }
    487 
    488  bool isUnknown() const {
    489    return !hasInt32LowerBound_ && !hasInt32UpperBound_ &&
    490           canHaveFractionalPart_ && canBeNegativeZero_ &&
    491           max_exponent_ == IncludesInfinityAndNaN;
    492  }
    493 
    494  bool hasInt32LowerBound() const { return hasInt32LowerBound_; }
    495  bool hasInt32UpperBound() const { return hasInt32UpperBound_; }
    496 
    497  // Test whether the value is known to be within [INT32_MIN,INT32_MAX].
    498  // Note that this does not necessarily mean the value is an integer.
    499  bool hasInt32Bounds() const {
    500    return hasInt32LowerBound() && hasInt32UpperBound();
    501  }
    502 
    503  // Test whether the value is known to be representable as an int32.
    504  bool isInt32() const {
    505    return hasInt32Bounds() && !canHaveFractionalPart_ && !canBeNegativeZero_;
    506  }
    507 
    508  // Test whether the given value is known to be either 0 or 1.
    509  bool isBoolean() const {
    510    return lower() >= 0 && upper() <= 1 && !canHaveFractionalPart_ &&
    511           !canBeNegativeZero_;
    512  }
    513 
    514  bool canHaveRoundingErrors() const {
    515    return canHaveFractionalPart_ || canBeNegativeZero_ ||
    516           max_exponent_ >= MaxTruncatableExponent;
    517  }
    518 
    519  // Test if an integer x belongs to the range.
    520  bool contains(int32_t x) const { return x >= lower_ && x <= upper_; }
    521 
    522  // Test whether the range contains zero (of either sign).
    523  bool canBeZero() const { return contains(0); }
    524 
    525  // Test whether the range contains NaN values.
    526  bool canBeNaN() const { return max_exponent_ == IncludesInfinityAndNaN; }
    527 
    528  // Test whether the range contains infinities or NaN values.
    529  bool canBeInfiniteOrNaN() const { return max_exponent_ >= IncludesInfinity; }
    530 
    531  FractionalPartFlag canHaveFractionalPart() const {
    532    return canHaveFractionalPart_;
    533  }
    534 
    535  NegativeZeroFlag canBeNegativeZero() const { return canBeNegativeZero_; }
    536 
    537  uint16_t exponent() const {
    538    MOZ_ASSERT(!canBeInfiniteOrNaN());
    539    return max_exponent_;
    540  }
    541 
    542  uint16_t numBits() const {
    543    return exponent() + 1;  // 2^0 -> 1
    544  }
    545 
    546  // Return the lower bound. Asserts that the value has an int32 bound.
    547  int32_t lower() const {
    548    MOZ_ASSERT(hasInt32LowerBound());
    549    return lower_;
    550  }
    551 
    552  // Return the upper bound. Asserts that the value has an int32 bound.
    553  int32_t upper() const {
    554    MOZ_ASSERT(hasInt32UpperBound());
    555    return upper_;
    556  }
    557 
    558  // Test whether all values in this range can are finite and negative.
    559  bool isFiniteNegative() const { return upper_ < 0 && !canBeInfiniteOrNaN(); }
    560 
    561  // Test whether all values in this range can are finite and non-negative.
    562  bool isFiniteNonNegative() const {
    563    return lower_ >= 0 && !canBeInfiniteOrNaN();
    564  }
    565 
    566  // Test whether a value in this range can possibly be a finite
    567  // negative value. Note that "negative zero" is not considered negative.
    568  bool canBeFiniteNegative() const { return lower_ < 0; }
    569 
    570  // Test whether a value in this range can possibly be a finite
    571  // non-negative value.
    572  bool canBeFiniteNonNegative() const { return upper_ >= 0; }
    573 
    574  // Test whether a value in this range can have the sign bit set (not
    575  // counting NaN, where the sign bit is meaningless).
    576  bool canHaveSignBitSet() const {
    577    return !hasInt32LowerBound() || canBeFiniteNegative() ||
    578           canBeNegativeZero();
    579  }
    580 
    581  // Set this range to have a lower bound not less than x.
    582  void refineLower(int32_t x) {
    583    assertInvariants();
    584    hasInt32LowerBound_ = true;
    585    lower_ = std::max(lower_, x);
    586    optimize();
    587  }
    588 
    589  // Set this range to have an upper bound not greater than x.
    590  void refineUpper(int32_t x) {
    591    assertInvariants();
    592    hasInt32UpperBound_ = true;
    593    upper_ = std::min(upper_, x);
    594    optimize();
    595  }
    596 
    597  // Set this range to exclude negative zero.
    598  void refineToExcludeNegativeZero() {
    599    assertInvariants();
    600    canBeNegativeZero_ = ExcludesNegativeZero;
    601    optimize();
    602  }
    603 
    604  void setInt32(int32_t l, int32_t h) {
    605    hasInt32LowerBound_ = true;
    606    hasInt32UpperBound_ = true;
    607    lower_ = l;
    608    upper_ = h;
    609    canHaveFractionalPart_ = ExcludesFractionalParts;
    610    canBeNegativeZero_ = ExcludesNegativeZero;
    611    max_exponent_ = exponentImpliedByInt32Bounds();
    612    assertInvariants();
    613  }
    614 
    615  // Set this range to include values >= l and <= h. Note that this
    616  // function treats negative zero as equal to zero, as >= and <= do. If the
    617  // range includes zero, it is assumed to include negative zero too.
    618  void setDouble(double l, double h);
    619 
    620  // Set this range to the narrowest possible range containing d.
    621  // This function treats negative zero as distinct from zero, since this
    622  // makes the narrowest possible range containin zero a range which
    623  // contains one value rather than two.
    624  void setDoubleSingleton(double d);
    625 
    626  void setUnknown() {
    627    set(NoInt32LowerBound, NoInt32UpperBound, IncludesFractionalParts,
    628        IncludesNegativeZero, IncludesInfinityAndNaN);
    629    MOZ_ASSERT(isUnknown());
    630  }
    631 
    632  void set(int64_t l, int64_t h, FractionalPartFlag canHaveFractionalPart,
    633           NegativeZeroFlag canBeNegativeZero, uint16_t e) {
    634    max_exponent_ = e;
    635    canHaveFractionalPart_ = canHaveFractionalPart;
    636    canBeNegativeZero_ = canBeNegativeZero;
    637    setLowerInit(l);
    638    setUpperInit(h);
    639    optimize();
    640  }
    641 
    642  // Make the lower end of this range at least INT32_MIN, and make
    643  // the upper end of this range at most INT32_MAX.
    644  void clampToInt32();
    645 
    646  // If this range exceeds int32_t range, at either or both ends, change
    647  // it to int32_t range.  Otherwise do nothing.
    648  void wrapAroundToInt32();
    649 
    650  // If this range exceeds [0, 32) range, at either or both ends, change
    651  // it to the [0, 32) range.  Otherwise do nothing.
    652  void wrapAroundToShiftCount();
    653 
    654  // If this range exceeds [0, 1] range, at either or both ends, change
    655  // it to the [0, 1] range.  Otherwise do nothing.
    656  void wrapAroundToBoolean();
    657 
    658  const SymbolicBound* symbolicLower() const { return symbolicLower_; }
    659  const SymbolicBound* symbolicUpper() const { return symbolicUpper_; }
    660 
    661  void setSymbolicLower(SymbolicBound* bound) { symbolicLower_ = bound; }
    662  void setSymbolicUpper(SymbolicBound* bound) { symbolicUpper_ = bound; }
    663 };
    664 
    665 }  // namespace jit
    666 }  // namespace js
    667 
    668 #endif /* jit_RangeAnalysis_h */