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