OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 5 #ifndef RUNTIME_VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
6 #define RUNTIME_VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 6 #define RUNTIME_VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
7 | 7 |
8 #include "vm/flow_graph.h" | 8 #include "vm/flow_graph.h" |
9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 class RangeBoundary : public ValueObject { | 13 class RangeBoundary : public ValueObject { |
14 public: | 14 public: |
15 enum Kind { | 15 enum Kind { |
16 kUnknown, | 16 kUnknown, |
17 kNegativeInfinity, | 17 kNegativeInfinity, |
18 kPositiveInfinity, | 18 kPositiveInfinity, |
19 kSymbol, | 19 kSymbol, |
20 kConstant, | 20 kConstant, |
21 }; | 21 }; |
22 | 22 |
23 enum RangeSize { | 23 enum RangeSize { |
24 kRangeBoundarySmi, | 24 kRangeBoundarySmi, |
25 kRangeBoundaryInt32, | 25 kRangeBoundaryInt32, |
26 kRangeBoundaryInt64, | 26 kRangeBoundaryInt64, |
27 }; | 27 }; |
28 | 28 |
29 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { } | 29 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) {} |
30 | 30 |
31 RangeBoundary(const RangeBoundary& other) | 31 RangeBoundary(const RangeBoundary& other) |
32 : ValueObject(), | 32 : ValueObject(), |
33 kind_(other.kind_), | 33 kind_(other.kind_), |
34 value_(other.value_), | 34 value_(other.value_), |
35 offset_(other.offset_) { } | 35 offset_(other.offset_) {} |
36 | 36 |
37 explicit RangeBoundary(int64_t val) | 37 explicit RangeBoundary(int64_t val) |
38 : kind_(kConstant), value_(val), offset_(0) { } | 38 : kind_(kConstant), value_(val), offset_(0) {} |
39 | 39 |
40 RangeBoundary& operator=(const RangeBoundary& other) { | 40 RangeBoundary& operator=(const RangeBoundary& other) { |
41 kind_ = other.kind_; | 41 kind_ = other.kind_; |
42 value_ = other.value_; | 42 value_ = other.value_; |
43 offset_ = other.offset_; | 43 offset_ = other.offset_; |
44 return *this; | 44 return *this; |
45 } | 45 } |
46 | 46 |
47 static const int64_t kMin = kMinInt64; | 47 static const int64_t kMin = kMinInt64; |
48 static const int64_t kMax = kMaxInt64; | 48 static const int64_t kMax = kMaxInt64; |
49 | 49 |
50 // Construct a RangeBoundary for a constant value. | 50 // Construct a RangeBoundary for a constant value. |
51 static RangeBoundary FromConstant(int64_t val) { | 51 static RangeBoundary FromConstant(int64_t val) { return RangeBoundary(val); } |
52 return RangeBoundary(val); | |
53 } | |
54 | 52 |
55 // Construct a RangeBoundary for -inf. | 53 // Construct a RangeBoundary for -inf. |
56 static RangeBoundary NegativeInfinity() { | 54 static RangeBoundary NegativeInfinity() { |
57 return RangeBoundary(kNegativeInfinity, 0, 0); | 55 return RangeBoundary(kNegativeInfinity, 0, 0); |
58 } | 56 } |
59 | 57 |
60 // Construct a RangeBoundary for +inf. | 58 // Construct a RangeBoundary for +inf. |
61 static RangeBoundary PositiveInfinity() { | 59 static RangeBoundary PositiveInfinity() { |
62 return RangeBoundary(kPositiveInfinity, 0, 0); | 60 return RangeBoundary(kPositiveInfinity, 0, 0); |
63 } | 61 } |
64 | 62 |
65 // Construct a RangeBoundary from a definition and offset. | 63 // Construct a RangeBoundary from a definition and offset. |
66 static RangeBoundary FromDefinition(Definition* defn, int64_t offs = 0); | 64 static RangeBoundary FromDefinition(Definition* defn, int64_t offs = 0); |
67 | 65 |
68 // Construct a RangeBoundary for the constant MinSmi value. | 66 // Construct a RangeBoundary for the constant MinSmi value. |
69 static RangeBoundary MinSmi() { | 67 static RangeBoundary MinSmi() { return FromConstant(Smi::kMinValue); } |
70 return FromConstant(Smi::kMinValue); | |
71 } | |
72 | 68 |
73 // Construct a RangeBoundary for the constant MaxSmi value. | 69 // Construct a RangeBoundary for the constant MaxSmi value. |
74 static RangeBoundary MaxSmi() { | 70 static RangeBoundary MaxSmi() { return FromConstant(Smi::kMaxValue); } |
75 return FromConstant(Smi::kMaxValue); | |
76 } | |
77 | 71 |
78 // Construct a RangeBoundary for the constant kMin value. | 72 // Construct a RangeBoundary for the constant kMin value. |
79 static RangeBoundary MinConstant() { | 73 static RangeBoundary MinConstant() { return FromConstant(kMin); } |
80 return FromConstant(kMin); | |
81 } | |
82 | 74 |
83 // Construct a RangeBoundary for the constant kMax value. | 75 // Construct a RangeBoundary for the constant kMax value. |
84 static RangeBoundary MaxConstant() { | 76 static RangeBoundary MaxConstant() { return FromConstant(kMax); } |
85 return FromConstant(kMax); | |
86 } | |
87 | 77 |
88 // Construct a RangeBoundary for the constant kMin value. | 78 // Construct a RangeBoundary for the constant kMin value. |
89 static RangeBoundary MinConstant(RangeSize size) { | 79 static RangeBoundary MinConstant(RangeSize size) { |
90 switch (size) { | 80 switch (size) { |
91 case kRangeBoundarySmi: | 81 case kRangeBoundarySmi: |
92 return FromConstant(Smi::kMinValue); | 82 return FromConstant(Smi::kMinValue); |
93 case kRangeBoundaryInt32: | 83 case kRangeBoundaryInt32: |
94 return FromConstant(kMinInt32); | 84 return FromConstant(kMinInt32); |
95 case kRangeBoundaryInt64: | 85 case kRangeBoundaryInt64: |
96 return FromConstant(kMinInt64); | 86 return FromConstant(kMinInt64); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 bool OverflowedSmi() const { | 139 bool OverflowedSmi() const { |
150 return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity(); | 140 return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity(); |
151 } | 141 } |
152 | 142 |
153 bool Overflowed(RangeBoundary::RangeSize size) const { | 143 bool Overflowed(RangeBoundary::RangeSize size) const { |
154 ASSERT(IsConstantOrInfinity()); | 144 ASSERT(IsConstantOrInfinity()); |
155 return !Equals(Clamp(size)); | 145 return !Equals(Clamp(size)); |
156 } | 146 } |
157 | 147 |
158 // Returns true if this outside mint range. | 148 // Returns true if this outside mint range. |
159 bool OverflowedMint() const { | 149 bool OverflowedMint() const { return IsInfinity(); } |
160 return IsInfinity(); | |
161 } | |
162 | 150 |
163 // -/+ infinity are clamped to MinConstant/MaxConstant of the given type. | 151 // -/+ infinity are clamped to MinConstant/MaxConstant of the given type. |
164 RangeBoundary Clamp(RangeSize size) const { | 152 RangeBoundary Clamp(RangeSize size) const { |
165 if (IsNegativeInfinity()) { | 153 if (IsNegativeInfinity()) { |
166 return RangeBoundary::MinConstant(size); | 154 return RangeBoundary::MinConstant(size); |
167 } | 155 } |
168 | 156 |
169 if (IsPositiveInfinity()) { | 157 if (IsPositiveInfinity()) { |
170 return RangeBoundary::MaxConstant(size); | 158 return RangeBoundary::MaxConstant(size); |
171 } | 159 } |
(...skipping 10 matching lines...) Expand all Loading... |
182 } | 170 } |
183 } | 171 } |
184 | 172 |
185 // If this range is a symbolic range, we do not clamp it. | 173 // If this range is a symbolic range, we do not clamp it. |
186 // This could lead to some imprecision later on. | 174 // This could lead to some imprecision later on. |
187 return *this; | 175 return *this; |
188 } | 176 } |
189 | 177 |
190 bool IsMinimumOrBelow(RangeSize size) const { | 178 bool IsMinimumOrBelow(RangeSize size) const { |
191 return IsNegativeInfinity() || | 179 return IsNegativeInfinity() || |
192 (IsConstant() && | 180 (IsConstant() && (ConstantValue() <= |
193 (ConstantValue() <= RangeBoundary::MinConstant(size).ConstantValue())); | 181 RangeBoundary::MinConstant(size).ConstantValue())); |
194 } | 182 } |
195 | 183 |
196 bool IsMaximumOrAbove(RangeSize size) const { | 184 bool IsMaximumOrAbove(RangeSize size) const { |
197 return IsPositiveInfinity() || | 185 return IsPositiveInfinity() || |
198 (IsConstant() && | 186 (IsConstant() && (ConstantValue() >= |
199 (ConstantValue() >= RangeBoundary::MaxConstant(size).ConstantValue())); | 187 RangeBoundary::MaxConstant(size).ConstantValue())); |
200 } | 188 } |
201 | 189 |
202 intptr_t kind() const { | 190 intptr_t kind() const { return kind_; } |
203 return kind_; | |
204 } | |
205 | 191 |
206 // Kind tests. | 192 // Kind tests. |
207 bool IsUnknown() const { return kind_ == kUnknown; } | 193 bool IsUnknown() const { return kind_ == kUnknown; } |
208 bool IsConstant() const { return kind_ == kConstant; } | 194 bool IsConstant() const { return kind_ == kConstant; } |
209 bool IsSymbol() const { return kind_ == kSymbol; } | 195 bool IsSymbol() const { return kind_ == kSymbol; } |
210 bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; } | 196 bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; } |
211 bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; } | 197 bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; } |
212 bool IsInfinity() const { | 198 bool IsInfinity() const { |
213 return IsNegativeInfinity() || IsPositiveInfinity(); | 199 return IsNegativeInfinity() || IsPositiveInfinity(); |
214 } | 200 } |
215 bool IsConstantOrInfinity() const { | 201 bool IsConstantOrInfinity() const { return IsConstant() || IsInfinity(); } |
216 return IsConstant() || IsInfinity(); | |
217 } | |
218 | 202 |
219 // Returns the value of a kConstant RangeBoundary. | 203 // Returns the value of a kConstant RangeBoundary. |
220 int64_t ConstantValue() const; | 204 int64_t ConstantValue() const; |
221 | 205 |
222 // Returns the Definition associated with a kSymbol RangeBoundary. | 206 // Returns the Definition associated with a kSymbol RangeBoundary. |
223 Definition* symbol() const { | 207 Definition* symbol() const { |
224 ASSERT(IsSymbol()); | 208 ASSERT(IsSymbol()); |
225 return reinterpret_cast<Definition*>(value_); | 209 return reinterpret_cast<Definition*>(value_); |
226 } | 210 } |
227 | 211 |
228 // Offset from symbol. | 212 // Offset from symbol. |
229 int64_t offset() const { | 213 int64_t offset() const { return offset_; } |
230 return offset_; | |
231 } | |
232 | 214 |
233 // Computes the LowerBound of this. Three cases: | 215 // Computes the LowerBound of this. Three cases: |
234 // IsInfinity() -> NegativeInfinity(). | 216 // IsInfinity() -> NegativeInfinity(). |
235 // IsConstant() -> value(). | 217 // IsConstant() -> value(). |
236 // IsSymbol() -> lower bound computed from definition + offset. | 218 // IsSymbol() -> lower bound computed from definition + offset. |
237 RangeBoundary LowerBound() const; | 219 RangeBoundary LowerBound() const; |
238 | 220 |
239 // Computes the UpperBound of this. Three cases: | 221 // Computes the UpperBound of this. Three cases: |
240 // IsInfinity() -> PositiveInfinity(). | 222 // IsInfinity() -> PositiveInfinity(). |
241 // IsConstant() -> value(). | 223 // IsConstant() -> value(). |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 bool Equals(const RangeBoundary& other) const; | 266 bool Equals(const RangeBoundary& other) const; |
285 | 267 |
286 int64_t UpperBound(RangeSize size) const { | 268 int64_t UpperBound(RangeSize size) const { |
287 return UpperBound().Clamp(size).ConstantValue(); | 269 return UpperBound().Clamp(size).ConstantValue(); |
288 } | 270 } |
289 | 271 |
290 int64_t LowerBound(RangeSize size) const { | 272 int64_t LowerBound(RangeSize size) const { |
291 return LowerBound().Clamp(size).ConstantValue(); | 273 return LowerBound().Clamp(size).ConstantValue(); |
292 } | 274 } |
293 | 275 |
294 int64_t SmiUpperBound() const { | 276 int64_t SmiUpperBound() const { return UpperBound(kRangeBoundarySmi); } |
295 return UpperBound(kRangeBoundarySmi); | |
296 } | |
297 | 277 |
298 int64_t SmiLowerBound() const { | 278 int64_t SmiLowerBound() const { return LowerBound(kRangeBoundarySmi); } |
299 return LowerBound(kRangeBoundarySmi); | |
300 } | |
301 | 279 |
302 private: | 280 private: |
303 RangeBoundary(Kind kind, int64_t value, int64_t offset) | 281 RangeBoundary(Kind kind, int64_t value, int64_t offset) |
304 : kind_(kind), value_(value), offset_(offset) { } | 282 : kind_(kind), value_(value), offset_(offset) {} |
305 | 283 |
306 Kind kind_; | 284 Kind kind_; |
307 int64_t value_; | 285 int64_t value_; |
308 int64_t offset_; | 286 int64_t offset_; |
309 }; | 287 }; |
310 | 288 |
311 | 289 |
312 class Range : public ZoneAllocated { | 290 class Range : public ZoneAllocated { |
313 public: | 291 public: |
314 Range() : min_(), max_() { } | 292 Range() : min_(), max_() {} |
315 Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { | 293 Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { |
316 ASSERT(min_.IsUnknown() == max_.IsUnknown()); | 294 ASSERT(min_.IsUnknown() == max_.IsUnknown()); |
317 } | 295 } |
318 | 296 |
319 Range(const Range& other) | 297 Range(const Range& other) |
320 : ZoneAllocated(), | 298 : ZoneAllocated(), min_(other.min_), max_(other.max_) {} |
321 min_(other.min_), | |
322 max_(other.max_) { | |
323 } | |
324 | 299 |
325 Range& operator=(const Range& other) { | 300 Range& operator=(const Range& other) { |
326 min_ = other.min_; | 301 min_ = other.min_; |
327 max_ = other.max_; | 302 max_ = other.max_; |
328 return *this; | 303 return *this; |
329 } | 304 } |
330 | 305 |
331 static bool IsUnknown(const Range* other) { | 306 static bool IsUnknown(const Range* other) { |
332 if (other == NULL) { | 307 if (other == NULL) { |
333 return true; | 308 return true; |
334 } | 309 } |
335 return other->min().IsUnknown(); | 310 return other->min().IsUnknown(); |
336 } | 311 } |
337 | 312 |
338 static Range Full(RangeBoundary::RangeSize size) { | 313 static Range Full(RangeBoundary::RangeSize size) { |
339 return Range(RangeBoundary::MinConstant(size), | 314 return Range(RangeBoundary::MinConstant(size), |
340 RangeBoundary::MaxConstant(size)); | 315 RangeBoundary::MaxConstant(size)); |
341 } | 316 } |
342 | 317 |
343 void PrintTo(BufferFormatter* f) const; | 318 void PrintTo(BufferFormatter* f) const; |
344 static const char* ToCString(const Range* range); | 319 static const char* ToCString(const Range* range); |
345 | 320 |
346 bool Equals(const Range* other) { | 321 bool Equals(const Range* other) { |
347 ASSERT(min_.IsUnknown() == max_.IsUnknown()); | 322 ASSERT(min_.IsUnknown() == max_.IsUnknown()); |
348 if (other == NULL) { | 323 if (other == NULL) { |
349 return min_.IsUnknown(); | 324 return min_.IsUnknown(); |
350 } | 325 } |
351 return min_.Equals(other->min_) && | 326 return min_.Equals(other->min_) && max_.Equals(other->max_); |
352 max_.Equals(other->max_); | |
353 } | 327 } |
354 | 328 |
355 const RangeBoundary& min() const { return min_; } | 329 const RangeBoundary& min() const { return min_; } |
356 const RangeBoundary& max() const { return max_; } | 330 const RangeBoundary& max() const { return max_; } |
357 void set_min(const RangeBoundary& value) { | 331 void set_min(const RangeBoundary& value) { min_ = value; } |
358 min_ = value; | 332 void set_max(const RangeBoundary& value) { max_ = value; } |
359 } | |
360 void set_max(const RangeBoundary& value) { | |
361 max_ = value; | |
362 } | |
363 | 333 |
364 static RangeBoundary ConstantMinSmi(const Range* range) { | 334 static RangeBoundary ConstantMinSmi(const Range* range) { |
365 return ConstantMin(range, RangeBoundary::kRangeBoundarySmi); | 335 return ConstantMin(range, RangeBoundary::kRangeBoundarySmi); |
366 } | 336 } |
367 | 337 |
368 static RangeBoundary ConstantMaxSmi(const Range* range) { | 338 static RangeBoundary ConstantMaxSmi(const Range* range) { |
369 return ConstantMax(range, RangeBoundary::kRangeBoundarySmi); | 339 return ConstantMax(range, RangeBoundary::kRangeBoundarySmi); |
370 } | 340 } |
371 | 341 |
372 static RangeBoundary ConstantMin(const Range* range) { | 342 static RangeBoundary ConstantMin(const Range* range) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 bool OnlyGreaterThanOrEqualTo(int64_t val) const; | 374 bool OnlyGreaterThanOrEqualTo(int64_t val) const; |
405 | 375 |
406 // Inclusive. | 376 // Inclusive. |
407 bool IsWithin(int64_t min_int, int64_t max_int) const; | 377 bool IsWithin(int64_t min_int, int64_t max_int) const; |
408 | 378 |
409 // Inclusive. | 379 // Inclusive. |
410 bool Overlaps(int64_t min_int, int64_t max_int) const; | 380 bool Overlaps(int64_t min_int, int64_t max_int) const; |
411 | 381 |
412 bool IsUnsatisfiable() const; | 382 bool IsUnsatisfiable() const; |
413 | 383 |
414 bool IsFinite() const { | 384 bool IsFinite() const { return !min_.IsInfinity() && !max_.IsInfinity(); } |
415 return !min_.IsInfinity() && !max_.IsInfinity(); | |
416 } | |
417 | 385 |
418 Range Intersect(const Range* other) const { | 386 Range Intersect(const Range* other) const { |
419 return Range(RangeBoundary::IntersectionMin(min(), other->min()), | 387 return Range(RangeBoundary::IntersectionMin(min(), other->min()), |
420 RangeBoundary::IntersectionMax(max(), other->max())); | 388 RangeBoundary::IntersectionMax(max(), other->max())); |
421 } | 389 } |
422 | 390 |
423 bool Fits(RangeBoundary::RangeSize size) const { | 391 bool Fits(RangeBoundary::RangeSize size) const { |
424 return !min().LowerBound().Overflowed(size) && | 392 return !min().LowerBound().Overflowed(size) && |
425 !max().UpperBound().Overflowed(size); | 393 !max().UpperBound().Overflowed(size); |
426 } | 394 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 const Range* right_range, | 449 const Range* right_range, |
482 Definition* left_defn, | 450 Definition* left_defn, |
483 Range* result); | 451 Range* result); |
484 | 452 |
485 private: | 453 private: |
486 RangeBoundary min_; | 454 RangeBoundary min_; |
487 RangeBoundary max_; | 455 RangeBoundary max_; |
488 }; | 456 }; |
489 | 457 |
490 | 458 |
491 class RangeUtils : public AllStatic { | 459 class RangeUtils : public AllStatic { |
492 public: | 460 public: |
493 static bool Fits(Range* range, RangeBoundary::RangeSize size) { | 461 static bool Fits(Range* range, RangeBoundary::RangeSize size) { |
494 return !Range::IsUnknown(range) && range->Fits(size); | 462 return !Range::IsUnknown(range) && range->Fits(size); |
495 } | 463 } |
496 | 464 |
497 static bool IsWithin(Range* range, int64_t min, int64_t max) { | 465 static bool IsWithin(Range* range, int64_t min, int64_t max) { |
498 return !Range::IsUnknown(range) && range->IsWithin(min, max); | 466 return !Range::IsUnknown(range) && range->IsWithin(min, max); |
499 } | 467 } |
500 | 468 |
501 static bool IsPositive(Range* range) { | 469 static bool IsPositive(Range* range) { |
502 return !Range::IsUnknown(range) && range->IsPositive(); | 470 return !Range::IsUnknown(range) && range->IsPositive(); |
503 } | 471 } |
504 }; | 472 }; |
505 | 473 |
506 | 474 |
507 // Range analysis for integer values. | 475 // Range analysis for integer values. |
508 class RangeAnalysis : public ValueObject { | 476 class RangeAnalysis : public ValueObject { |
509 public: | 477 public: |
510 explicit RangeAnalysis(FlowGraph* flow_graph) | 478 explicit RangeAnalysis(FlowGraph* flow_graph) |
511 : flow_graph_(flow_graph), | 479 : flow_graph_(flow_graph), |
512 smi_range_(Range::Full(RangeBoundary::kRangeBoundarySmi)), | 480 smi_range_(Range::Full(RangeBoundary::kRangeBoundarySmi)), |
513 int64_range_(Range::Full(RangeBoundary::kRangeBoundaryInt64)) { } | 481 int64_range_(Range::Full(RangeBoundary::kRangeBoundaryInt64)) {} |
514 | 482 |
515 // Infer ranges for all values and remove overflow checks from binary smi | 483 // Infer ranges for all values and remove overflow checks from binary smi |
516 // operations when proven redundant. | 484 // operations when proven redundant. |
517 void Analyze(); | 485 void Analyze(); |
518 | 486 |
519 // Helper that should be used to access ranges of inputs during range | 487 // Helper that should be used to access ranges of inputs during range |
520 // inference. | 488 // inference. |
521 // Returns meaningful results for uses of non-smi/non-int definitions that | 489 // Returns meaningful results for uses of non-smi/non-int definitions that |
522 // have smi/int as a reaching type. | 490 // have smi/int as a reaching type. |
523 // For Int typed definitions we use full Int64 range as a safe approximation | 491 // For Int typed definitions we use full Int64 range as a safe approximation |
524 // even though they might contain Bigint values because we only support | 492 // even though they might contain Bigint values because we only support |
525 // 64-bit operations in the optimized code - which means that Bigint will | 493 // 64-bit operations in the optimized code - which means that Bigint will |
526 // cause deoptimization. | 494 // cause deoptimization. |
527 const Range* GetSmiRange(Value* value) const; | 495 const Range* GetSmiRange(Value* value) const; |
528 const Range* GetIntRange(Value* value) const; | 496 const Range* GetIntRange(Value* value) const; |
529 | 497 |
530 static bool IsIntegerDefinition(Definition* defn) { | 498 static bool IsIntegerDefinition(Definition* defn) { |
531 return defn->Type()->IsInt(); | 499 return defn->Type()->IsInt(); |
532 } | 500 } |
533 | 501 |
534 void AssignRangesRecursively(Definition* defn); | 502 void AssignRangesRecursively(Definition* defn); |
535 | 503 |
536 private: | 504 private: |
537 enum JoinOperator { | 505 enum JoinOperator { NONE, WIDEN, NARROW }; |
538 NONE, | |
539 WIDEN, | |
540 NARROW | |
541 }; | |
542 static char OpPrefix(JoinOperator op); | 506 static char OpPrefix(JoinOperator op); |
543 | 507 |
544 // Collect all values that were proven to be smi in smi_values_ array and all | 508 // Collect all values that were proven to be smi in smi_values_ array and all |
545 // CheckSmi instructions in smi_check_ array. | 509 // CheckSmi instructions in smi_check_ array. |
546 void CollectValues(); | 510 void CollectValues(); |
547 | 511 |
548 // Iterate over smi values and constrain them at branch successors. | 512 // Iterate over smi values and constrain them at branch successors. |
549 // Additionally constraint values after CheckSmi instructions. | 513 // Additionally constraint values after CheckSmi instructions. |
550 void InsertConstraints(); | 514 void InsertConstraints(); |
551 | 515 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 BitVector* selected_uint32_defs_; | 621 BitVector* selected_uint32_defs_; |
658 | 622 |
659 FlowGraph* flow_graph_; | 623 FlowGraph* flow_graph_; |
660 Zone* zone_; | 624 Zone* zone_; |
661 }; | 625 }; |
662 | 626 |
663 | 627 |
664 } // namespace dart | 628 } // namespace dart |
665 | 629 |
666 #endif // RUNTIME_VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 630 #endif // RUNTIME_VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
OLD | NEW |