|
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/. */ |
|
6 |
|
7 #ifndef jit_RangeAnalysis_h |
|
8 #define jit_RangeAnalysis_h |
|
9 |
|
10 #include "mozilla/FloatingPoint.h" |
|
11 #include "mozilla/MathAlgorithms.h" |
|
12 |
|
13 #include "jit/IonAnalysis.h" |
|
14 #include "jit/MIR.h" |
|
15 |
|
16 // windows.h defines those, which messes with the definitions below. |
|
17 #undef min |
|
18 #undef max |
|
19 |
|
20 namespace js { |
|
21 namespace jit { |
|
22 |
|
23 class MBasicBlock; |
|
24 class MIRGraph; |
|
25 |
|
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; |
|
34 |
|
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; |
|
40 |
|
41 // Symbolic bound computed for the number of backedge executions. |
|
42 LinearSum sum; |
|
43 |
|
44 LoopIterationBound(MBasicBlock *header, MTest *test, LinearSum sum) |
|
45 : header(header), test(test), sum(sum) |
|
46 { |
|
47 } |
|
48 }; |
|
49 |
|
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 } |
|
58 |
|
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; |
|
67 |
|
68 static SymbolicBound *New(TempAllocator &alloc, LoopIterationBound *loop, LinearSum sum) { |
|
69 return new(alloc) SymbolicBound(loop, sum); |
|
70 } |
|
71 |
|
72 // Computed symbolic bound, see above. |
|
73 LinearSum sum; |
|
74 |
|
75 void print(Sprinter &sp) const; |
|
76 void dump() const; |
|
77 }; |
|
78 |
|
79 class RangeAnalysis |
|
80 { |
|
81 protected: |
|
82 bool blockDominates(MBasicBlock *b, MBasicBlock *b2); |
|
83 void replaceDominatedUsesWith(MDefinition *orig, MDefinition *dom, |
|
84 MBasicBlock *block); |
|
85 |
|
86 protected: |
|
87 MIRGenerator *mir; |
|
88 MIRGraph &graph_; |
|
89 |
|
90 TempAllocator &alloc() const; |
|
91 |
|
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(); |
|
101 |
|
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 }; |
|
110 |
|
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; |
|
116 |
|
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; |
|
120 |
|
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; |
|
125 |
|
126 // Maximum exponent for finite values. |
|
127 static const uint16_t MaxFiniteExponent = mozilla::FloatingPoint<double>::ExponentBias; |
|
128 |
|
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; |
|
132 |
|
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; |
|
136 |
|
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; |
|
145 |
|
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. |
|
176 |
|
177 int32_t lower_; |
|
178 bool hasInt32LowerBound_; |
|
179 |
|
180 int32_t upper_; |
|
181 bool hasInt32UpperBound_; |
|
182 |
|
183 bool canHaveFractionalPart_; |
|
184 uint16_t max_exponent_; |
|
185 |
|
186 // Any symbolic lower or upper bound computed for this term. |
|
187 const SymbolicBound *symbolicLower_; |
|
188 const SymbolicBound *symbolicUpper_; |
|
189 |
|
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_); |
|
195 |
|
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); |
|
201 |
|
202 // max_exponent_ must be one of three possible things. |
|
203 JS_ASSERT(max_exponent_ <= MaxFiniteExponent || |
|
204 max_exponent_ == IncludesInfinity || |
|
205 max_exponent_ == IncludesInfinityAndNaN); |
|
206 |
|
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_))); |
|
221 |
|
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 } |
|
229 |
|
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 } |
|
256 |
|
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 } |
|
270 |
|
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 } |
|
288 |
|
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(); |
|
294 |
|
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 } |
|
304 |
|
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 } |
|
313 |
|
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 } |
|
324 |
|
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 } |
|
332 |
|
333 public: |
|
334 Range() |
|
335 : symbolicLower_(nullptr), |
|
336 symbolicUpper_(nullptr) |
|
337 { |
|
338 setUnknown(); |
|
339 } |
|
340 |
|
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 } |
|
347 |
|
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 } |
|
360 |
|
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); |
|
365 |
|
366 static Range *NewInt32Range(TempAllocator &alloc, int32_t l, int32_t h) { |
|
367 return new(alloc) Range(l, h, false, MaxInt32Exponent); |
|
368 } |
|
369 |
|
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 } |
|
375 |
|
376 static Range *NewDoubleRange(TempAllocator &alloc, double l, double h) { |
|
377 if (mozilla::IsNaN(l) && mozilla::IsNaN(h)) |
|
378 return nullptr; |
|
379 |
|
380 Range *r = new(alloc) Range(); |
|
381 r->setDouble(l, h); |
|
382 return r; |
|
383 } |
|
384 |
|
385 void print(Sprinter &sp) const; |
|
386 void dump(FILE *fp) const; |
|
387 void dump() const; |
|
388 bool update(const Range *other); |
|
389 |
|
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); |
|
413 |
|
414 static bool negativeZeroMul(const Range *lhs, const Range *rhs); |
|
415 |
|
416 bool isUnknownInt32() const { |
|
417 return isInt32() && lower() == INT32_MIN && upper() == INT32_MAX; |
|
418 } |
|
419 |
|
420 bool isUnknown() const { |
|
421 return !hasInt32LowerBound_ && |
|
422 !hasInt32UpperBound_ && |
|
423 canHaveFractionalPart_ && |
|
424 max_exponent_ == IncludesInfinityAndNaN; |
|
425 } |
|
426 |
|
427 bool hasInt32LowerBound() const { |
|
428 return hasInt32LowerBound_; |
|
429 } |
|
430 bool hasInt32UpperBound() const { |
|
431 return hasInt32UpperBound_; |
|
432 } |
|
433 |
|
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 } |
|
439 |
|
440 // Test whether the value is known to be representable as an int32. |
|
441 bool isInt32() const { |
|
442 return hasInt32Bounds() && !canHaveFractionalPart(); |
|
443 } |
|
444 |
|
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 } |
|
449 |
|
450 bool canHaveRoundingErrors() const { |
|
451 return canHaveFractionalPart() || max_exponent_ >= MaxTruncatableExponent; |
|
452 } |
|
453 |
|
454 // Test whether the range contains zero. |
|
455 bool canBeZero() const { |
|
456 return lower_ <= 0 && upper_ >= 0; |
|
457 } |
|
458 |
|
459 // Test whether the range contains NaN values. |
|
460 bool canBeNaN() const { |
|
461 return max_exponent_ == IncludesInfinityAndNaN; |
|
462 } |
|
463 |
|
464 // Test whether the range contains infinities or NaN values. |
|
465 bool canBeInfiniteOrNaN() const { |
|
466 return max_exponent_ >= IncludesInfinity; |
|
467 } |
|
468 |
|
469 bool canHaveFractionalPart() const { |
|
470 return canHaveFractionalPart_; |
|
471 } |
|
472 |
|
473 uint16_t exponent() const { |
|
474 JS_ASSERT(!canBeInfiniteOrNaN()); |
|
475 return max_exponent_; |
|
476 } |
|
477 |
|
478 uint16_t numBits() const { |
|
479 return exponent() + 1; // 2^0 -> 1 |
|
480 } |
|
481 |
|
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 } |
|
487 |
|
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 } |
|
493 |
|
494 // Test whether all values in this range can are finite and negative. |
|
495 bool isFiniteNegative() const { |
|
496 return upper_ < 0 && !canBeInfiniteOrNaN(); |
|
497 } |
|
498 |
|
499 // Test whether all values in this range can are finite and non-negative. |
|
500 bool isFiniteNonNegative() const { |
|
501 return lower_ >= 0 && !canBeInfiniteOrNaN(); |
|
502 } |
|
503 |
|
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 } |
|
509 |
|
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 } |
|
515 |
|
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 } |
|
523 |
|
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 } |
|
531 |
|
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 } |
|
541 |
|
542 void setDouble(double l, double h); |
|
543 |
|
544 void setUnknown() { |
|
545 set(NoInt32LowerBound, NoInt32UpperBound, true, IncludesInfinityAndNaN); |
|
546 JS_ASSERT(isUnknown()); |
|
547 } |
|
548 |
|
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 } |
|
556 |
|
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(); |
|
560 |
|
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(); |
|
564 |
|
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(); |
|
568 |
|
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(); |
|
572 |
|
573 const SymbolicBound *symbolicLower() const { |
|
574 return symbolicLower_; |
|
575 } |
|
576 const SymbolicBound *symbolicUpper() const { |
|
577 return symbolicUpper_; |
|
578 } |
|
579 |
|
580 void setSymbolicLower(SymbolicBound *bound) { |
|
581 symbolicLower_ = bound; |
|
582 } |
|
583 void setSymbolicUpper(SymbolicBound *bound) { |
|
584 symbolicUpper_ = bound; |
|
585 } |
|
586 }; |
|
587 |
|
588 } // namespace jit |
|
589 } // namespace js |
|
590 |
|
591 #endif /* jit_RangeAnalysis_h */ |