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 */