Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
range_analysis.h
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_BACKEND_RANGE_ANALYSIS_H_
6#define RUNTIME_VM_COMPILER_BACKEND_RANGE_ANALYSIS_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
14
15namespace dart {
16
17class RangeBoundary : public ValueObject {
18 public:
19#define FOR_EACH_RANGE_BOUNDARY_KIND(V) \
20 V(Unknown) \
21 V(Symbol) \
22 V(Constant)
23
24#define KIND_DEFN(name) k##name,
26#undef KIND_DEFN
27
35
36 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) {}
37
39 : ValueObject(),
40 kind_(other.kind_),
41 value_(other.value_),
42 offset_(other.offset_) {}
43
44 explicit RangeBoundary(int64_t val)
45 : kind_(kConstant), value_(val), offset_(0) {}
46
48 kind_ = other.kind_;
49 value_ = other.value_;
50 offset_ = other.offset_;
51 return *this;
52 }
53
54 static constexpr int64_t kMin = kMinInt64;
55 static constexpr int64_t kMax = kMaxInt64;
56
57 // Construct a RangeBoundary for a constant value.
58 static RangeBoundary FromConstant(int64_t val) { return RangeBoundary(val); }
59
60 // Construct a RangeBoundary from a definition and offset.
61 static RangeBoundary FromDefinition(Definition* defn, int64_t offs = 0);
62
64 if ((offset > (kMaxInt64 - compiler::target::kSmiMax)) ||
65 (offset < (kMinInt64 - compiler::target::kSmiMin))) {
66 // Avoid creating symbolic range boundaries which can wrap around.
67 return false;
68 }
69 return true;
70 }
71
72 // Construct a RangeBoundary for the constant MinSmi value.
74 return FromConstant(compiler::target::kSmiMin);
75 }
76
77 // Construct a RangeBoundary for the constant MaxSmi value.
79 return FromConstant(compiler::target::kSmiMax);
80 }
81
82 // Construct a RangeBoundary for the constant kMin value.
84 switch (size) {
86 return FromConstant(compiler::target::kSmiMin);
88 return FromConstant(kMinInt8);
90 return FromConstant(kMinInt16);
92 return FromConstant(kMinInt32);
94 return FromConstant(kMinInt64);
95 }
97 return FromConstant(kMinInt64);
98 }
99
101 switch (size) {
103 return FromConstant(compiler::target::kSmiMax);
105 return FromConstant(kMaxInt8);
107 return FromConstant(kMaxInt16);
109 return FromConstant(kMaxInt32);
111 return FromConstant(kMaxInt64);
112 }
113 UNREACHABLE();
114 return FromConstant(kMaxInt64);
115 }
116
117 // Given two boundaries a and b, select one of them as c so that
118 //
119 // inf {[a, ...) ^ [b, ...)} >= inf {c}
120 //
122
123 // Given two boundaries a and b, select one of them as c so that
124 //
125 // sup {(..., a] ^ (..., b]} <= sup {c}
126 //
128
129 // Given two boundaries a and b compute boundary c such that
130 //
131 // inf {[a, ...) U [b, ...)} >= inf {c}
132 //
133 // Try to select c such that it is as close to inf {[a, ...) U [b, ...)}
134 // as possible.
138
139 // Given two boundaries a and b compute boundary c such that
140 //
141 // sup {(..., a] U (..., b]} <= sup {c}
142 //
143 // Try to select c such that it is as close to sup {(..., a] U (..., b]}
144 // as possible.
148
149 // Returns true when this is a constant that is outside of Smi range.
150 bool OverflowedSmi() const {
152 }
153
156 return !Equals(Clamp(size));
157 }
158
159 // Clamp constant boundary to MinConstant/MaxConstant of the given size.
161 if (IsConstant()) {
162 const RangeBoundary range_min = RangeBoundary::MinConstant(size);
163 const RangeBoundary range_max = RangeBoundary::MaxConstant(size);
164
165 if (ConstantValue() <= range_min.ConstantValue()) {
166 return range_min;
167 }
168 if (ConstantValue() >= range_max.ConstantValue()) {
169 return range_max;
170 }
171 }
172
173 // If this range is a symbolic range, we do not clamp it.
174 // This could lead to some imprecision later on.
175 return *this;
176 }
177
178 bool IsMinimumOrBelow(RangeSize size) const {
179 return IsConstant() && (ConstantValue() <=
181 }
182
183 bool IsMaximumOrAbove(RangeSize size) const {
184 return IsConstant() && (ConstantValue() >=
186 }
187
188 intptr_t kind() const { return kind_; }
189
190 // Kind tests.
191 bool IsUnknown() const { return kind_ == kUnknown; }
192 bool IsConstant() const { return kind_ == kConstant; }
193 bool IsSymbol() const { return kind_ == kSymbol; }
194
195 // Returns the value of a kConstant RangeBoundary.
196 int64_t ConstantValue() const;
197
198 // Returns the Definition associated with a kSymbol RangeBoundary.
200 ASSERT(IsSymbol());
201 return reinterpret_cast<Definition*>(value_);
202 }
203
204 // Offset from symbol.
205 int64_t offset() const { return offset_; }
206
207 // Computes the LowerBound of this. Three cases:
208 // IsConstant() -> value().
209 // IsSymbol() -> lower bound computed from definition + offset.
211
212 // Computes the UpperBound of this. Three cases:
213 // IsConstant() -> value().
214 // IsSymbol() -> upper bound computed from definition + offset.
216
217 void PrintTo(BaseTextBuffer* f) const;
218 const char* ToCString() const;
219
220 static bool WillAddOverflow(const RangeBoundary& a, const RangeBoundary& b);
221
222 static RangeBoundary Add(const RangeBoundary& a, const RangeBoundary& b);
223
224 static bool WillSubOverflow(const RangeBoundary& a, const RangeBoundary& b);
225
226 static RangeBoundary Sub(const RangeBoundary& a, const RangeBoundary& b);
227
228 static bool WillShlOverflow(const RangeBoundary& a, int64_t shift_count);
229
230 static RangeBoundary Shl(const RangeBoundary& value_boundary,
231 int64_t shift_count);
232
233 static RangeBoundary Shr(const RangeBoundary& value_boundary,
234 int64_t shift_count);
235
236 // Attempts to calculate a + b when:
237 // a is a symbol and b is a constant OR
238 // a is a constant and b is a symbol
239 // returns true if it succeeds, output is in result.
240 static bool SymbolicAdd(const RangeBoundary& a,
241 const RangeBoundary& b,
243
244 // Attempts to calculate a - b when:
245 // a is a symbol and b is a constant
246 // returns true if it succeeds, output is in result.
247 static bool SymbolicSub(const RangeBoundary& a,
248 const RangeBoundary& b,
250
251 bool Equals(const RangeBoundary& other) const;
252
253 int64_t UpperBound(RangeSize size) const {
254 return UpperBound().Clamp(size).ConstantValue();
255 }
256
257 int64_t LowerBound(RangeSize size) const {
258 return LowerBound().Clamp(size).ConstantValue();
259 }
260
261 int64_t SmiUpperBound() const { return UpperBound(kRangeBoundarySmi); }
262
263 int64_t SmiLowerBound() const { return LowerBound(kRangeBoundarySmi); }
264
265 void Write(FlowGraphSerializer* s) const;
267
268 private:
269 RangeBoundary(Kind kind, int64_t value, int64_t offset)
270 : kind_(kind), value_(value), offset_(offset) {}
271
272 Kind kind_;
273 int64_t value_;
274 int64_t offset_;
275};
276
277class Range : public ZoneAllocated {
278 public:
279 Range() : min_(), max_() {}
280
282 ASSERT(min_.IsUnknown() == max_.IsUnknown());
283 }
284
285 Range(const Range& other)
286 : ZoneAllocated(), min_(other.min_), max_(other.max_) {}
287
288 Range& operator=(const Range& other) {
289 min_ = other.min_;
290 max_ = other.max_;
291 return *this;
292 }
293
294 static bool IsUnknown(const Range* other) {
295 if (other == nullptr) {
296 return true;
297 }
298 return other->min().IsUnknown();
299 }
300
305
306 static Range Full(Representation rep);
307
308 void PrintTo(BaseTextBuffer* f) const;
309 static const char* ToCString(const Range* range);
310
311 bool Equals(const Range* other) {
312 ASSERT(min_.IsUnknown() == max_.IsUnknown());
313 if (other == nullptr) {
314 return min_.IsUnknown();
315 }
316 return min_.Equals(other->min_) && max_.Equals(other->max_);
317 }
318
319 const RangeBoundary& min() const { return min_; }
320 const RangeBoundary& max() const { return max_; }
321
322 void set_min(const RangeBoundary& value) { min_ = value; }
323
324 void set_max(const RangeBoundary& value) { max_ = value; }
325
326 static RangeBoundary ConstantMinSmi(const Range* range) {
328 }
329
330 static RangeBoundary ConstantMaxSmi(const Range* range) {
332 }
333
334 static RangeBoundary ConstantMin(const Range* range) {
336 }
337
338 static RangeBoundary ConstantMax(const Range* range) {
340 }
341
342 static RangeBoundary ConstantMin(const Range* range,
344 if (range == nullptr) {
345 return RangeBoundary::MinConstant(size);
346 }
347 return range->min().LowerBound().Clamp(size);
348 }
349
350 static RangeBoundary ConstantMax(const Range* range,
352 if (range == nullptr) {
353 return RangeBoundary::MaxConstant(size);
354 }
355 return range->max().UpperBound().Clamp(size);
356 }
357
358 // [0, +inf]
359 bool IsPositive() const;
360
361 // [-inf, -1]
362 bool IsNegative() const;
363
364 // [-inf, val].
365 bool OnlyLessThanOrEqualTo(int64_t val) const;
366
367 // [val, +inf].
368 bool OnlyGreaterThanOrEqualTo(int64_t val) const;
369
370 // Inclusive.
371 bool IsWithin(int64_t min_int, int64_t max_int) const;
372
373 // Inclusive.
374 bool IsWithin(const Range* other) const;
375
376 // Inclusive.
377 bool Overlaps(int64_t min_int, int64_t max_int) const;
378
379 bool IsUnsatisfiable() const;
380
381 bool IsSingleton() const {
382 return min_.IsConstant() && max_.IsConstant() &&
383 min_.ConstantValue() == max_.ConstantValue();
384 }
385
386 int64_t Singleton() const {
388 return min_.ConstantValue();
389 }
390
391 Range Intersect(const Range* other) const {
392 return Range(RangeBoundary::IntersectionMin(min(), other->min()),
394 }
395
397 return !min().LowerBound().Overflowed(size) &&
398 !max().UpperBound().Overflowed(size);
399 }
400
401 // Returns true if this range fits without truncation into
402 // the given representation.
403 static bool Fits(Range* range, Representation rep) {
404 if (range == nullptr) return false;
405 if (!RepresentationUtils::IsUnboxedInteger(rep)) return false;
406 const Range& other = Range::Full(rep);
407 return range->IsWithin(&other);
408 }
409
410 // Clamp this to be within size.
412
413 // Clamp this to be within size and eliminate symbols.
415
416 static void Add(const Range* left_range,
417 const Range* right_range,
420 Definition* left_defn);
421
422 static void Sub(const Range* left_range,
423 const Range* right_range,
426 Definition* left_defn);
427
428 static void Mul(const Range* left_range,
429 const Range* right_range,
432
433 static void TruncDiv(const Range* left_range,
434 const Range* right_range,
437
438 static void Mod(const Range* right_range,
441
442 static void Shr(const Range* left_range,
443 const Range* right_range,
446
447 static void Ushr(const Range* left_range,
448 const Range* right_range,
451
452 static void Shl(const Range* left_range,
453 const Range* right_range,
456
457 static void And(const Range* left_range,
458 const Range* right_range,
461
462 static void BitwiseOp(const Range* left_range,
463 const Range* right_range,
466
467 // Both the a and b ranges are >= 0.
468 static bool OnlyPositiveOrZero(const Range& a, const Range& b);
469
470 // Both the a and b ranges are <= 0.
471 static bool OnlyNegativeOrZero(const Range& a, const Range& b);
472
473 // Return the maximum absolute value included in range.
474 static int64_t ConstantAbsMax(const Range* range);
475
476 // Return the minimum absolute value included in range.
477 static int64_t ConstantAbsMin(const Range* range);
478
479 static void BinaryOp(const Token::Kind op,
480 const Range* left_range,
481 const Range* right_range,
482 Definition* left_defn,
483 Range* result);
484
485 void Write(FlowGraphSerializer* s) const;
486 explicit Range(FlowGraphDeserializer* d);
487
488 private:
489 RangeBoundary min_;
490 RangeBoundary max_;
491};
492
493class RangeUtils : public AllStatic {
494 public:
495 static bool Fits(Range* range, RangeBoundary::RangeSize size) {
496 return !Range::IsUnknown(range) && range->Fits(size);
497 }
498
499 static bool IsWithin(const Range* range, int64_t min, int64_t max) {
500 return !Range::IsUnknown(range) && range->IsWithin(min, max);
501 }
502
503 static bool IsWithin(const Range* range, const Range* other) {
504 return !Range::IsUnknown(range) && range->IsWithin(other);
505 }
506
507 static bool IsPositive(Range* range) {
508 return !Range::IsUnknown(range) && range->IsPositive();
509 }
510 static bool IsNegative(Range* range) {
511 return !Range::IsUnknown(range) && range->IsNegative();
512 }
513
514 static bool Overlaps(Range* range, intptr_t min, intptr_t max) {
515 return Range::IsUnknown(range) || range->Overlaps(min, max);
516 }
517
518 static bool CanBeZero(Range* range) { return Overlaps(range, 0, 0); }
519
520 static bool OnlyLessThanOrEqualTo(Range* range, intptr_t value) {
521 return !Range::IsUnknown(range) && range->OnlyLessThanOrEqualTo(value);
522 }
523
524 static bool IsSingleton(Range* range) {
525 return !Range::IsUnknown(range) && range->IsSingleton();
526 }
527};
528
529// Range analysis for integer values.
531 public:
532 explicit RangeAnalysis(FlowGraph* flow_graph)
533 : flow_graph_(flow_graph),
534 smi_range_(Range::Full(RangeBoundary::kRangeBoundarySmi)),
535 int64_range_(Range::Full(RangeBoundary::kRangeBoundaryInt64)) {}
536
537 // Infer ranges for all values and remove overflow checks from binary smi
538 // operations when proven redundant.
539 void Analyze();
540
541 // Helper that should be used to access ranges of inputs during range
542 // inference.
543 // Returns meaningful results for uses of non-smi/non-int definitions that
544 // have smi/int as a reaching type.
545 const Range* GetSmiRange(Value* value) const;
546 const Range* GetIntRange(Value* value) const;
547
548 static bool IsIntegerDefinition(Definition* defn) {
549 return defn->Type()->IsInt();
550 }
551
553
554 private:
555 enum JoinOperator { NONE, WIDEN, NARROW };
556 static char OpPrefix(JoinOperator op);
557
558 // Collect all integer values (smi or int), all 64-bit binary
559 // and shift operations, and all check bounds.
560 void CollectValues();
561
562 // Iterate over smi values and constrain them at branch successors.
563 // Additionally constraint values after CheckSmi instructions.
564 void InsertConstraints();
565
566 // Iterate over uses of the given definition and discover branches that
567 // constrain it. Insert appropriate Constraint instructions at true
568 // and false successor and rename all dominated uses to refer to a
569 // Constraint instead of this definition.
570 void InsertConstraintsFor(Definition* defn);
571
572 // Create a constraint for defn, insert it after given instruction and
573 // rename all uses that are dominated by it.
574 ConstraintInstr* InsertConstraintFor(Value* use,
575 Definition* defn,
576 Range* constraint,
577 Instruction* after);
578
579 bool ConstrainValueAfterBranch(Value* use, Definition* defn);
580 void ConstrainValueAfterCheckBound(Value* use,
581 CheckBoundBaseInstr* check,
582 Definition* defn);
583
584 // Infer ranges for integer (smi or mint) definitions.
585 void InferRanges();
586
587 // Collect integer definition in the reverse postorder.
588 void CollectDefinitions(BitVector* set);
589
590 // Recompute ranges of all definitions until they stop changing.
591 // Apply the given JoinOperator when computing Phi ranges.
592 void Iterate(JoinOperator op, intptr_t max_iterations);
593 bool InferRange(JoinOperator op, Definition* defn, intptr_t iteration);
594
595 // Based on computed ranges find and eliminate redundant CheckArrayBound
596 // instructions.
597 void EliminateRedundantBoundsChecks();
598
599 // Find unsatisfiable constraints and mark corresponding blocks unreachable.
600 void MarkUnreachableBlocks();
601
602 // Convert mint operations that stay within int32 range into Int32 operations.
603 void NarrowMintToInt32();
604
605 // Remove artificial Constraint instructions and replace them with actual
606 // unconstrained definitions.
607 void RemoveConstraints();
608
609 Range* ConstraintSmiRange(Token::Kind op, Definition* boundary);
610
611 Zone* zone() const { return flow_graph_->zone(); }
612
613 FlowGraph* flow_graph_;
614
615 // Range object representing full Smi range.
616 Range smi_range_;
617
618 Range int64_range_;
619
620 // All values that are known to be smi or mint.
621 GrowableArray<Definition*> values_;
622
623 // All 64-bit binary and shift operations.
624 GrowableArray<BinaryInt64OpInstr*> binary_int64_ops_;
625 GrowableArray<ShiftIntegerOpInstr*> shift_int64_ops_;
626
627 // All CheckArrayBound/GenericCheckBound instructions.
628 GrowableArray<CheckBoundBaseInstr*> bounds_checks_;
629
630 // All Constraints inserted during InsertConstraints phase. They are treated
631 // as smi values.
632 GrowableArray<ConstraintInstr*> constraints_;
633
634 // List of integer (smi or mint) definitions including constraints sorted
635 // in the reverse postorder.
636 GrowableArray<Definition*> definitions_;
637
638 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis);
639};
640
641// Replaces Mint IL instructions with Uint32 IL instructions
642// when possible. Uses output of RangeAnalysis.
644 public:
645 explicit IntegerInstructionSelector(FlowGraph* flow_graph);
646
647 void Select();
648
649 private:
650 bool IsPotentialUint32Definition(Definition* def);
651 void FindPotentialUint32Definitions();
652 bool IsUint32NarrowingDefinition(Definition* def);
653 void FindUint32NarrowingDefinitions();
654 bool AllUsesAreUint32Narrowing(Value* list_head);
655 bool CanBecomeUint32(Definition* def);
656 void Propagate();
657 Definition* ConstructReplacementFor(Definition* def);
658 void ReplaceInstructions();
659
660 Zone* zone() const { return zone_; }
661
662 GrowableArray<Definition*> potential_uint32_defs_;
663 BitVector* selected_uint32_defs_;
664
665 FlowGraph* flow_graph_;
666 Zone* zone_;
667};
668
669} // namespace dart
670
671#endif // RUNTIME_VM_COMPILER_BACKEND_RANGE_ANALYSIS_H_
#define check(reporter, ref, unref, make, kill)
#define UNREACHABLE()
Definition assert.h:248
CompileType * Type()
Definition il.h:2503
Zone * zone() const
Definition flow_graph.h:261
void AssignRangesRecursively(Definition *defn)
const Range * GetIntRange(Value *value) const
static bool IsIntegerDefinition(Definition *defn)
const Range * GetSmiRange(Value *value) const
RangeAnalysis(FlowGraph *flow_graph)
RangeBoundary(int64_t val)
int64_t UpperBound(RangeSize size) const
bool Equals(const RangeBoundary &other) const
bool IsConstant() const
bool OverflowedSmi() const
static bool WillSubOverflow(const RangeBoundary &a, const RangeBoundary &b)
static RangeBoundary FromDefinition(Definition *defn, int64_t offs=0)
int64_t offset() const
void Write(FlowGraphSerializer *s) const
int64_t SmiLowerBound() const
int64_t SmiUpperBound() const
static RangeBoundary MaxSmi()
RangeBoundary Clamp(RangeSize size) const
static bool SymbolicAdd(const RangeBoundary &a, const RangeBoundary &b, RangeBoundary *result)
static bool IsValidOffsetForSymbolicRangeBoundary(int64_t offset)
int64_t LowerBound(RangeSize size) const
bool IsMaximumOrAbove(RangeSize size) const
static bool WillAddOverflow(const RangeBoundary &a, const RangeBoundary &b)
static RangeBoundary MinConstant(RangeSize size)
static RangeBoundary Add(const RangeBoundary &a, const RangeBoundary &b)
RangeBoundary UpperBound() const
static constexpr int64_t kMin
static RangeBoundary JoinMax(RangeBoundary a, RangeBoundary b, RangeBoundary::RangeSize size)
RangeBoundary LowerBound() const
static bool SymbolicSub(const RangeBoundary &a, const RangeBoundary &b, RangeBoundary *result)
static RangeBoundary IntersectionMin(RangeBoundary a, RangeBoundary b)
static RangeBoundary MinSmi()
static RangeBoundary Shr(const RangeBoundary &value_boundary, int64_t shift_count)
static RangeBoundary IntersectionMax(RangeBoundary a, RangeBoundary b)
int64_t ConstantValue() const
static RangeBoundary JoinMin(RangeBoundary a, RangeBoundary b, RangeBoundary::RangeSize size)
static constexpr int64_t kMax
static RangeBoundary Sub(const RangeBoundary &a, const RangeBoundary &b)
RangeBoundary & operator=(const RangeBoundary &other)
RangeBoundary(const RangeBoundary &other)
static RangeBoundary Shl(const RangeBoundary &value_boundary, int64_t shift_count)
intptr_t kind() const
static RangeBoundary MaxConstant(RangeSize size)
static bool WillShlOverflow(const RangeBoundary &a, int64_t shift_count)
const char * ToCString() const
void PrintTo(BaseTextBuffer *f) const
bool Overflowed(RangeBoundary::RangeSize size) const
bool IsMinimumOrBelow(RangeSize size) const
static RangeBoundary FromConstant(int64_t val)
Definition * symbol() const
static bool IsSingleton(Range *range)
static bool IsNegative(Range *range)
static bool Overlaps(Range *range, intptr_t min, intptr_t max)
static bool OnlyLessThanOrEqualTo(Range *range, intptr_t value)
static bool Fits(Range *range, RangeBoundary::RangeSize size)
static bool IsWithin(const Range *range, int64_t min, int64_t max)
static bool IsPositive(Range *range)
static bool CanBeZero(Range *range)
static bool IsWithin(const Range *range, const Range *other)
static RangeBoundary ConstantMinSmi(const Range *range)
static int64_t ConstantAbsMax(const Range *range)
static bool OnlyNegativeOrZero(const Range &a, const Range &b)
static void BitwiseOp(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max)
bool IsPositive() const
static const char * ToCString(const Range *range)
void set_max(const RangeBoundary &value)
static RangeBoundary ConstantMin(const Range *range, RangeBoundary::RangeSize size)
static void Shr(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max)
static bool Fits(Range *range, Representation rep)
static RangeBoundary ConstantMaxSmi(const Range *range)
bool IsWithin(int64_t min_int, int64_t max_int) const
Range Intersect(const Range *other) const
void ClampToConstant(RangeBoundary::RangeSize size)
Range & operator=(const Range &other)
static void Mul(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max)
Range(RangeBoundary min, RangeBoundary max)
bool IsNegative() const
static bool OnlyPositiveOrZero(const Range &a, const Range &b)
static bool IsUnknown(const Range *other)
static void TruncDiv(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max)
static void Ushr(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max)
const RangeBoundary & min() const
bool IsUnsatisfiable() const
bool Fits(RangeBoundary::RangeSize size) const
static void BinaryOp(const Token::Kind op, const Range *left_range, const Range *right_range, Definition *left_defn, Range *result)
const RangeBoundary & max() const
Range(const Range &other)
static void Add(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max, Definition *left_defn)
static void And(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max)
static Range Full(RangeBoundary::RangeSize size)
static void Sub(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max, Definition *left_defn)
void Clamp(RangeBoundary::RangeSize size)
static RangeBoundary ConstantMax(const Range *range, RangeBoundary::RangeSize size)
void Write(FlowGraphSerializer *s) const
static void Shl(const Range *left_range, const Range *right_range, RangeBoundary *min, RangeBoundary *max)
bool Equals(const Range *other)
bool OnlyGreaterThanOrEqualTo(int64_t val) const
static RangeBoundary ConstantMin(const Range *range)
void set_min(const RangeBoundary &value)
static void Mod(const Range *right_range, RangeBoundary *min, RangeBoundary *max)
void PrintTo(BaseTextBuffer *f) const
bool OnlyLessThanOrEqualTo(int64_t val) const
static RangeBoundary ConstantMax(const Range *range)
bool Overlaps(int64_t min_int, int64_t max_int) const
static int64_t ConstantAbsMin(const Range *range)
int64_t Singleton() const
bool IsSingleton() const
#define ASSERT(E)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
static bool b
struct MyStruct s
struct MyStruct a[10]
uint8_t value
GAsyncResult * result
static float max(float r, float g, float b)
Definition hsl.cpp:49
static float min(float r, float g, float b)
Definition hsl.cpp:48
#define KIND_DEFN(name)
Definition il.h:4364
bool IsSmi(int64_t v)
constexpr int16_t kMaxInt16
Definition globals.h:480
constexpr int64_t kMaxInt64
Definition globals.h:486
constexpr int64_t kMinInt64
Definition globals.h:485
constexpr int32_t kMinInt32
Definition globals.h:482
Representation
Definition locations.h:66
constexpr int8_t kMaxInt8
Definition globals.h:477
constexpr int32_t kMaxInt32
Definition globals.h:483
constexpr int16_t kMinInt16
Definition globals.h:479
constexpr int8_t kMinInt8
Definition globals.h:476
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition globals.h:581
static constexpr bool IsUnboxedInteger(Representation rep)
Definition locations.h:92