Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: runtime/vm/flow_graph_range_analysis.cc

Issue 504143003: Support Int32 representation for selected binary operations. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include "vm/flow_graph_range_analysis.h" 5 #include "vm/flow_graph_range_analysis.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/il_printer.h" 8 #include "vm/il_printer.h"
9 9
10 namespace dart { 10 namespace dart {
(...skipping 13 matching lines...) Expand all
24 24
25 if (FLAG_trace_range_analysis) { 25 if (FLAG_trace_range_analysis) {
26 FlowGraphPrinter::PrintGraph("Range Analysis (BBB)", flow_graph_); 26 FlowGraphPrinter::PrintGraph("Range Analysis (BBB)", flow_graph_);
27 } 27 }
28 28
29 InsertConstraints(); 29 InsertConstraints();
30 InferRanges(); 30 InferRanges();
31 EliminateRedundantBoundsChecks(); 31 EliminateRedundantBoundsChecks();
32 MarkUnreachableBlocks(); 32 MarkUnreachableBlocks();
33 33
34 NarrowMintToInt32();
35
34 IntegerInstructionSelector iis(flow_graph_); 36 IntegerInstructionSelector iis(flow_graph_);
35 iis.Select(); 37 iis.Select();
36 38
37 RemoveConstraints(); 39 RemoveConstraints();
38 } 40 }
39 41
40 42
41 void RangeAnalysis::CollectValues() { 43 void RangeAnalysis::CollectValues() {
42 const GrowableArray<Definition*>& initial = 44 const GrowableArray<Definition*>& initial =
43 *flow_graph_->graph_entry()->initial_definitions(); 45 *flow_graph_->graph_entry()->initial_definitions();
44 for (intptr_t i = 0; i < initial.length(); ++i) { 46 for (intptr_t i = 0; i < initial.length(); ++i) {
45 Definition* current = initial[i]; 47 Definition* current = initial[i];
46 if (current->Type()->ToCid() == kSmiCid) { 48 if (current->Type()->ToCid() == kSmiCid) {
47 values_.Add(current); 49 values_.Add(current);
48 } else if (current->IsMintDefinition()) { 50 } else if (current->IsMintDefinition()) {
49 values_.Add(current); 51 values_.Add(current);
52 } else if (current->IsInt32Definition()) {
53 values_.Add(current);
50 } 54 }
51 } 55 }
52 56
53 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); 57 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
54 !block_it.Done(); 58 !block_it.Done();
55 block_it.Advance()) { 59 block_it.Advance()) {
56 BlockEntryInstr* block = block_it.Current(); 60 BlockEntryInstr* block = block_it.Current();
57 61
58 62
59 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) { 63 if (block->IsGraphEntry() || block->IsCatchBlockEntry()) {
60 const GrowableArray<Definition*>& initial = block->IsGraphEntry() 64 const GrowableArray<Definition*>& initial = block->IsGraphEntry()
61 ? *block->AsGraphEntry()->initial_definitions() 65 ? *block->AsGraphEntry()->initial_definitions()
62 : *block->AsCatchBlockEntry()->initial_definitions(); 66 : *block->AsCatchBlockEntry()->initial_definitions();
63 for (intptr_t i = 0; i < initial.length(); ++i) { 67 for (intptr_t i = 0; i < initial.length(); ++i) {
64 Definition* current = initial[i]; 68 Definition* current = initial[i];
65 if (current->Type()->ToCid() == kSmiCid) { 69 if (current->Type()->ToCid() == kSmiCid) {
66 values_.Add(current); 70 values_.Add(current);
67 } else if (current->IsMintDefinition()) { 71 } else if (current->IsMintDefinition()) {
68 values_.Add(current); 72 values_.Add(current);
73 } else if (current->IsInt32Definition()) {
74 values_.Add(current);
69 } 75 }
70 } 76 }
71 } 77 }
72 78
73 JoinEntryInstr* join = block->AsJoinEntry(); 79 JoinEntryInstr* join = block->AsJoinEntry();
74 if (join != NULL) { 80 if (join != NULL) {
75 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) { 81 for (PhiIterator phi_it(join); !phi_it.Done(); phi_it.Advance()) {
76 PhiInstr* current = phi_it.Current(); 82 PhiInstr* current = phi_it.Current();
77 if (current->Type()->ToCid() == kSmiCid) { 83 if (current->Type()->ToCid() == kSmiCid) {
78 values_.Add(current); 84 values_.Add(current);
85 } else if (current->representation() == kUnboxedInt32) {
86 values_.Add(current);
79 } 87 }
80 } 88 }
81 } 89 }
82 90
83 for (ForwardInstructionIterator instr_it(block); 91 for (ForwardInstructionIterator instr_it(block);
84 !instr_it.Done(); 92 !instr_it.Done();
85 instr_it.Advance()) { 93 instr_it.Advance()) {
86 Instruction* current = instr_it.Current(); 94 Instruction* current = instr_it.Current();
87 Definition* defn = current->AsDefinition(); 95 Definition* defn = current->AsDefinition();
88 if (defn != NULL) { 96 if (defn != NULL) {
89 if ((defn->Type()->ToCid() == kSmiCid) && 97 if ((defn->Type()->ToCid() == kSmiCid) &&
90 (defn->ssa_temp_index() != -1)) { 98 (defn->ssa_temp_index() != -1)) {
91 values_.Add(defn); 99 values_.Add(defn);
92 } else if ((defn->IsMintDefinition()) && 100 } else if ((defn->IsMintDefinition()) &&
93 (defn->ssa_temp_index() != -1)) { 101 (defn->ssa_temp_index() != -1)) {
94 values_.Add(defn); 102 values_.Add(defn);
103 if (defn->IsBinaryMintOp()) {
104 binary_mint_ops_.Add(defn->AsBinaryMintOp());
105 } else if (defn->IsShiftMintOp()) {
106 shift_mint_ops_.Add(defn->AsShiftMintOp());
107 }
108 } else if (defn->IsInt32Definition()) {
109 values_.Add(defn);
95 } 110 }
96 } else if (current->IsCheckArrayBound()) { 111 } else if (current->IsCheckArrayBound()) {
97 bounds_checks_.Add(current->AsCheckArrayBound()); 112 bounds_checks_.Add(current->AsCheckArrayBound());
98 } 113 }
99 } 114 }
100 } 115 }
101 } 116 }
102 117
103 118
104 // Returns true if use is dominated by the given instruction. 119 // Returns true if use is dominated by the given instruction.
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 378
364 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { 379 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) {
365 return a.IsSymbol() && b.IsSymbol() && 380 return a.IsSymbol() && b.IsSymbol() &&
366 AreEqualDefinitions(a.symbol(), b.symbol()); 381 AreEqualDefinitions(a.symbol(), b.symbol());
367 } 382 }
368 383
369 384
370 // Given the current range of a phi and a newly computed range check 385 // Given the current range of a phi and a newly computed range check
371 // if it is growing towards negative infinity, if it does widen it to 386 // if it is growing towards negative infinity, if it does widen it to
372 // MinSmi. 387 // MinSmi.
373 static RangeBoundary WidenMin(const Range* range, const Range* new_range) { 388 static RangeBoundary WidenMin(const Range* range,
389 const Range* new_range,
390 RangeBoundary::RangeSize size) {
374 RangeBoundary min = range->min(); 391 RangeBoundary min = range->min();
375 RangeBoundary new_min = new_range->min(); 392 RangeBoundary new_min = new_range->min();
376 393
377 if (min.IsSymbol()) { 394 if (min.IsSymbol()) {
378 if (min.LowerBound().OverflowedSmi()) { 395 if (min.LowerBound().Overflowed(size)) {
379 return RangeBoundary::MinSmi(); 396 return RangeBoundary::MinConstant(size);
380 } else if (DependOnSameSymbol(min, new_min)) { 397 } else if (DependOnSameSymbol(min, new_min)) {
381 return min.offset() <= new_min.offset() ? min : RangeBoundary::MinSmi(); 398 return min.offset() <= new_min.offset() ?
382 } else if (min.SmiUpperBound() <= new_min.SmiLowerBound()) { 399 min : RangeBoundary::MinConstant(size);
400 } else if (min.UpperBound(size) <= new_min.LowerBound(size)) {
383 return min; 401 return min;
384 } 402 }
385 } 403 }
386 404
387 min = Range::ConstantMinSmi(range); 405 min = Range::ConstantMin(range, size);
388 new_min = Range::ConstantMinSmi(new_range); 406 new_min = Range::ConstantMin(new_range, size);
389 407
390 return (min.ConstantValue() <= new_min.ConstantValue()) ? 408 return (min.ConstantValue() <= new_min.ConstantValue()) ?
391 min : RangeBoundary::MinSmi(); 409 min : RangeBoundary::MinConstant(size);
392 } 410 }
393 411
394 // Given the current range of a phi and a newly computed range check 412 // Given the current range of a phi and a newly computed range check
395 // if it is growing towards positive infinity, if it does widen it to 413 // if it is growing towards positive infinity, if it does widen it to
396 // MaxSmi. 414 // MaxSmi.
397 static RangeBoundary WidenMax(const Range* range, const Range* new_range) { 415 static RangeBoundary WidenMax(const Range* range,
416 const Range* new_range,
417 RangeBoundary::RangeSize size) {
398 RangeBoundary max = range->max(); 418 RangeBoundary max = range->max();
399 RangeBoundary new_max = new_range->max(); 419 RangeBoundary new_max = new_range->max();
400 420
401 if (max.IsSymbol()) { 421 if (max.IsSymbol()) {
402 if (max.UpperBound().OverflowedSmi()) { 422 if (max.UpperBound().Overflowed(size)) {
403 return RangeBoundary::MaxSmi(); 423 return RangeBoundary::MaxConstant(size);
404 } else if (DependOnSameSymbol(max, new_max)) { 424 } else if (DependOnSameSymbol(max, new_max)) {
405 return max.offset() >= new_max.offset() ? max : RangeBoundary::MaxSmi(); 425 return max.offset() >= new_max.offset() ?
406 } else if (max.SmiLowerBound() >= new_max.SmiUpperBound()) { 426 max : RangeBoundary::MaxConstant(size);
427 } else if (max.LowerBound(size) >= new_max.UpperBound(size)) {
407 return max; 428 return max;
408 } 429 }
409 } 430 }
410 431
411 max = Range::ConstantMaxSmi(range); 432 max = Range::ConstantMax(range, size);
412 new_max = Range::ConstantMaxSmi(new_range); 433 new_max = Range::ConstantMax(new_range, size);
413 434
414 return (max.ConstantValue() >= new_max.ConstantValue()) ? 435 return (max.ConstantValue() >= new_max.ConstantValue()) ?
415 max : RangeBoundary::MaxSmi(); 436 max : RangeBoundary::MaxConstant(size);
416 } 437 }
417 438
418 439
419 // Given the current range of a phi and a newly computed range check 440 // Given the current range of a phi and a newly computed range check
420 // if we can perform narrowing: use newly computed minimum to improve precision 441 // if we can perform narrowing: use newly computed minimum to improve precision
421 // of the computed range. We do it only if current minimum was widened and is 442 // of the computed range. We do it only if current minimum was widened and is
422 // equal to MinSmi. 443 // equal to MinSmi.
423 // Newly computed minimum is expected to be greater of equal then old one as 444 // Newly computed minimum is expected to be greater of equal then old one as
424 // we are running after widening phase. 445 // we are running after widening phase.
425 static RangeBoundary NarrowMin(const Range* range, const Range* new_range) { 446 static RangeBoundary NarrowMin(const Range* range,
447 const Range* new_range,
448 RangeBoundary::RangeSize size) {
426 #ifdef DEBUG 449 #ifdef DEBUG
427 const RangeBoundary min = Range::ConstantMinSmi(range); 450 const RangeBoundary min = Range::ConstantMin(range, size);
428 const RangeBoundary new_min = Range::ConstantMinSmi(new_range); 451 const RangeBoundary new_min = Range::ConstantMin(new_range, size);
429 ASSERT(min.ConstantValue() <= new_min.ConstantValue()); 452 ASSERT(min.ConstantValue() <= new_min.ConstantValue());
430 #endif 453 #endif
431 // TODO(vegorov): consider using negative infinity to indicate widened bound. 454 // TODO(vegorov): consider using negative infinity to indicate widened bound.
432 return range->min().IsSmiMinimumOrBelow() ? new_range->min() : range->min(); 455 return range->min().IsMinimumOrBelow(size) ? new_range->min() : range->min();
433 } 456 }
434 457
435 458
436 // Given the current range of a phi and a newly computed range check 459 // Given the current range of a phi and a newly computed range check
437 // if we can perform narrowing: use newly computed maximum to improve precision 460 // if we can perform narrowing: use newly computed maximum to improve precision
438 // of the computed range. We do it only if current maximum was widened and is 461 // of the computed range. We do it only if current maximum was widened and is
439 // equal to MaxSmi. 462 // equal to MaxSmi.
440 // Newly computed minimum is expected to be greater of equal then old one as 463 // Newly computed minimum is expected to be greater of equal then old one as
441 // we are running after widening phase. 464 // we are running after widening phase.
442 static RangeBoundary NarrowMax(const Range* range, const Range* new_range) { 465 static RangeBoundary NarrowMax(const Range* range,
466 const Range* new_range,
467 RangeBoundary::RangeSize size) {
443 #ifdef DEBUG 468 #ifdef DEBUG
444 const RangeBoundary max = Range::ConstantMaxSmi(range); 469 const RangeBoundary max = Range::ConstantMax(range, size);
445 const RangeBoundary new_max = Range::ConstantMaxSmi(new_range); 470 const RangeBoundary new_max = Range::ConstantMax(new_range, size);
446 ASSERT(max.ConstantValue() >= new_max.ConstantValue()); 471 ASSERT(max.ConstantValue() >= new_max.ConstantValue());
447 #endif 472 #endif
448 // TODO(vegorov): consider using positive infinity to indicate widened bound. 473 // TODO(vegorov): consider using positive infinity to indicate widened bound.
449 return range->max().IsSmiMaximumOrAbove() ? new_range->max() : range->max(); 474 return range->max().IsMaximumOrAbove(size) ? new_range->max() : range->max();
450 } 475 }
451 476
452 477
453 char RangeAnalysis::OpPrefix(JoinOperator op) { 478 char RangeAnalysis::OpPrefix(JoinOperator op) {
454 switch (op) { 479 switch (op) {
455 case WIDEN: return 'W'; 480 case WIDEN: return 'W';
456 case NARROW: return 'N'; 481 case NARROW: return 'N';
457 case NONE: return 'I'; 482 case NONE: return 'I';
458 } 483 }
459 UNREACHABLE(); 484 UNREACHABLE();
460 return ' '; 485 return ' ';
461 } 486 }
462 487
463 488
464 bool RangeAnalysis::InferRange(JoinOperator op, 489 bool RangeAnalysis::InferRange(JoinOperator op,
465 Definition* defn, 490 Definition* defn,
466 intptr_t iteration) { 491 intptr_t iteration) {
467 Range range; 492 Range range;
468 defn->InferRange(this, &range); 493 defn->InferRange(this, &range);
469 494
470 if (!Range::IsUnknown(&range)) { 495 if (!Range::IsUnknown(&range)) {
471 if (!Range::IsUnknown(defn->range()) && defn->IsPhi()) { 496 if (!Range::IsUnknown(defn->range()) && defn->IsPhi()) {
472 // TODO(vegorov): we are currently supporting only smi phis. 497 // TODO(vegorov): we are currently supporting only smi/int32 phis.
473 ASSERT(defn->Type()->ToCid() == kSmiCid); 498 ASSERT((defn->Type()->ToCid() == kSmiCid) ||
499 (defn->representation() == kUnboxedInt32));
500 const RangeBoundary::RangeSize size = (defn->Type()->ToCid() == kSmiCid) ?
501 RangeBoundary::kRangeBoundarySmi : RangeBoundary::kRangeBoundaryInt32;
474 if (op == WIDEN) { 502 if (op == WIDEN) {
475 range = Range(WidenMin(defn->range(), &range), 503 range = Range(WidenMin(defn->range(), &range, size),
476 WidenMax(defn->range(), &range)); 504 WidenMax(defn->range(), &range, size));
477 } else if (op == NARROW) { 505 } else if (op == NARROW) {
478 range = Range(NarrowMin(defn->range(), &range), 506 range = Range(NarrowMin(defn->range(), &range, size),
479 NarrowMax(defn->range(), &range)); 507 NarrowMax(defn->range(), &range, size));
480 } 508 }
481 } 509 }
482 510
483 if (!range.Equals(defn->range())) { 511 if (!range.Equals(defn->range())) {
484 if (FLAG_trace_range_analysis) { 512 if (FLAG_trace_range_analysis) {
485 OS::Print("%c [%" Pd "] %s: %s => %s\n", 513 OS::Print("%c [%" Pd "] %s: %s => %s\n",
486 OpPrefix(op), 514 OpPrefix(op),
487 iteration, 515 iteration,
488 defn->ToCString(), 516 defn->ToCString(),
489 Range::ToCString(defn->range()), 517 Range::ToCString(defn->range()),
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 // constraints until we reach the actual definition. 679 // constraints until we reach the actual definition.
652 while (def->IsConstraint()) { 680 while (def->IsConstraint()) {
653 def = def->AsConstraint()->value()->definition(); 681 def = def->AsConstraint()->value()->definition();
654 } 682 }
655 constraints_[i]->ReplaceUsesWith(def); 683 constraints_[i]->ReplaceUsesWith(def);
656 constraints_[i]->RemoveFromGraph(); 684 constraints_[i]->RemoveFromGraph();
657 } 685 }
658 } 686 }
659 687
660 688
689 static void NarrowBinaryMintOp(BinaryMintOpInstr* mint_op) {
690 if (Range::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) &&
691 Range::Fits(mint_op->left()->definition()->range(),
692 RangeBoundary::kRangeBoundaryInt32) &&
693 Range::Fits(mint_op->right()->definition()->range(),
694 RangeBoundary::kRangeBoundaryInt32) &&
695 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(),
696 mint_op->left(),
697 mint_op->right())) {
698 BinaryInt32OpInstr* int32_op =
699 new BinaryInt32OpInstr(mint_op->op_kind(),
700 mint_op->left()->CopyWithType(),
701 mint_op->right()->CopyWithType(),
702 mint_op->DeoptimizationTarget());
703 int32_op->set_range(*mint_op->range());
704 int32_op->set_overflow(false);
705 mint_op->ReplaceWith(int32_op, NULL);
706 }
707 }
708
709
710 static void NarrowShiftMintOp(ShiftMintOpInstr* mint_op) {
711 if (Range::Fits(mint_op->range(), RangeBoundary::kRangeBoundaryInt32) &&
712 Range::Fits(mint_op->left()->definition()->range(),
713 RangeBoundary::kRangeBoundaryInt32) &&
714 Range::Fits(mint_op->right()->definition()->range(),
715 RangeBoundary::kRangeBoundaryInt32) &&
716 BinaryInt32OpInstr::IsSupported(mint_op->op_kind(),
717 mint_op->left(),
718 mint_op->right())) {
719 BinaryInt32OpInstr* int32_op =
720 new BinaryInt32OpInstr(mint_op->op_kind(),
721 mint_op->left()->CopyWithType(),
722 mint_op->right()->CopyWithType(),
723 mint_op->DeoptimizationTarget());
724 int32_op->set_range(*mint_op->range());
725 int32_op->set_overflow(false);
726 mint_op->ReplaceWith(int32_op, NULL);
727 }
728 }
729
730
731 void RangeAnalysis::NarrowMintToInt32() {
732 for (intptr_t i = 0; i < binary_mint_ops_.length(); i++) {
733 NarrowBinaryMintOp(binary_mint_ops_[i]);
734 }
735
736 for (intptr_t i = 0; i < shift_mint_ops_.length(); i++) {
737 NarrowShiftMintOp(shift_mint_ops_[i]);
738 }
739 }
740
741
661 IntegerInstructionSelector::IntegerInstructionSelector(FlowGraph* flow_graph) 742 IntegerInstructionSelector::IntegerInstructionSelector(FlowGraph* flow_graph)
662 : flow_graph_(flow_graph), 743 : flow_graph_(flow_graph),
663 isolate_(NULL) { 744 isolate_(NULL) {
664 ASSERT(flow_graph_ != NULL); 745 ASSERT(flow_graph_ != NULL);
665 isolate_ = flow_graph_->isolate(); 746 isolate_ = flow_graph_->isolate();
666 ASSERT(isolate_ != NULL); 747 ASSERT(isolate_ != NULL);
667 selected_uint32_defs_ = 748 selected_uint32_defs_ =
668 new(I) BitVector(flow_graph_->current_ssa_temp_index()); 749 new(I) BitVector(flow_graph_->current_ssa_temp_index());
669 } 750 }
670 751
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
897 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) { 978 if (!selected_uint32_defs_->Contains(defn->ssa_temp_index())) {
898 // Not a candidate. 979 // Not a candidate.
899 continue; 980 continue;
900 } 981 }
901 Definition* replacement = ConstructReplacementFor(defn); 982 Definition* replacement = ConstructReplacementFor(defn);
902 ASSERT(replacement != NULL); 983 ASSERT(replacement != NULL);
903 if (FLAG_trace_integer_ir_selection) { 984 if (FLAG_trace_integer_ir_selection) {
904 OS::Print("Replacing %s with %s\n", defn->ToCString(), 985 OS::Print("Replacing %s with %s\n", defn->ToCString(),
905 replacement->ToCString()); 986 replacement->ToCString());
906 } 987 }
988 if (!Range::IsUnknown(defn->range())) {
989 replacement->set_range(*defn->range());
990 }
907 defn->ReplaceWith(replacement, NULL); 991 defn->ReplaceWith(replacement, NULL);
908 ASSERT(flow_graph_->VerifyUseLists()); 992 ASSERT(flow_graph_->VerifyUseLists());
909 } 993 }
910 } 994 }
911 995
912 996
913 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, int64_t offs) { 997 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, int64_t offs) {
914 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { 998 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) {
915 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); 999 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs);
916 } 1000 }
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 *a = canonical_a; 1254 *a = canonical_a;
1171 *b = canonical_b; 1255 *b = canonical_b;
1172 return true; 1256 return true;
1173 } 1257 }
1174 } while (op(&canonical_a) || op(&canonical_b)); 1258 } while (op(&canonical_a) || op(&canonical_b));
1175 1259
1176 return false; 1260 return false;
1177 } 1261 }
1178 1262
1179 1263
1180 RangeBoundary RangeBoundary::JoinMin(RangeBoundary a, RangeBoundary b) { 1264 RangeBoundary RangeBoundary::JoinMin(RangeBoundary a,
1265 RangeBoundary b,
1266 RangeBoundary::RangeSize size) {
1181 if (a.Equals(b)) { 1267 if (a.Equals(b)) {
1182 return b; 1268 return b;
1183 } 1269 }
1184 1270
1185 if (CanonicalizeForComparison(&a, 1271 if (CanonicalizeForComparison(&a,
1186 &b, 1272 &b,
1187 &CanonicalizeMinBoundary, 1273 &CanonicalizeMinBoundary,
1188 RangeBoundary::NegativeInfinity())) { 1274 RangeBoundary::NegativeInfinity())) {
1189 return (a.offset() <= b.offset()) ? a : b; 1275 return (a.offset() <= b.offset()) ? a : b;
1190 } 1276 }
1191 1277
1192 const int64_t inf_a = a.SmiLowerBound(); 1278 const int64_t inf_a = a.LowerBound(size);
1193 const int64_t inf_b = b.SmiLowerBound(); 1279 const int64_t inf_b = b.LowerBound(size);
1194 const int64_t sup_a = a.SmiUpperBound(); 1280 const int64_t sup_a = a.UpperBound(size);
1195 const int64_t sup_b = b.SmiUpperBound(); 1281 const int64_t sup_b = b.UpperBound(size);
1196 1282
1197 if ((sup_a <= inf_b) && !a.LowerBound().OverflowedSmi()) { 1283 if ((sup_a <= inf_b) && !a.LowerBound().Overflowed(size)) {
1198 return a; 1284 return a;
1199 } else if ((sup_b <= inf_a) && !b.LowerBound().OverflowedSmi()) { 1285 } else if ((sup_b <= inf_a) && !b.LowerBound().Overflowed(size)) {
1200 return b; 1286 return b;
1201 } else { 1287 } else {
1202 return RangeBoundary::FromConstant(Utils::Minimum(inf_a, inf_b)); 1288 return RangeBoundary::FromConstant(Utils::Minimum(inf_a, inf_b));
1203 } 1289 }
1204 } 1290 }
1205 1291
1206 1292
1207 RangeBoundary RangeBoundary::JoinMax(RangeBoundary a, RangeBoundary b) { 1293 RangeBoundary RangeBoundary::JoinMax(RangeBoundary a,
1294 RangeBoundary b,
1295 RangeBoundary::RangeSize size) {
1208 if (a.Equals(b)) { 1296 if (a.Equals(b)) {
1209 return b; 1297 return b;
1210 } 1298 }
1211 1299
1212 if (CanonicalizeForComparison(&a, 1300 if (CanonicalizeForComparison(&a,
1213 &b, 1301 &b,
1214 &CanonicalizeMaxBoundary, 1302 &CanonicalizeMaxBoundary,
1215 RangeBoundary::PositiveInfinity())) { 1303 RangeBoundary::PositiveInfinity())) {
1216 return (a.offset() >= b.offset()) ? a : b; 1304 return (a.offset() >= b.offset()) ? a : b;
1217 } 1305 }
1218 1306
1219 const int64_t inf_a = a.SmiLowerBound(); 1307 const int64_t inf_a = a.LowerBound(size);
1220 const int64_t inf_b = b.SmiLowerBound(); 1308 const int64_t inf_b = b.LowerBound(size);
1221 const int64_t sup_a = a.SmiUpperBound(); 1309 const int64_t sup_a = a.UpperBound(size);
1222 const int64_t sup_b = b.SmiUpperBound(); 1310 const int64_t sup_b = b.UpperBound(size);
1223 1311
1224 if ((sup_a <= inf_b) && !b.UpperBound().OverflowedSmi()) { 1312 if ((sup_a <= inf_b) && !b.UpperBound().Overflowed(size)) {
1225 return b; 1313 return b;
1226 } else if ((sup_b <= inf_a) && !a.UpperBound().OverflowedSmi()) { 1314 } else if ((sup_b <= inf_a) && !a.UpperBound().Overflowed(size)) {
1227 return a; 1315 return a;
1228 } else { 1316 } else {
1229 return RangeBoundary::FromConstant(Utils::Maximum(sup_a, sup_b)); 1317 return RangeBoundary::FromConstant(Utils::Maximum(sup_a, sup_b));
1230 } 1318 }
1231 } 1319 }
1232 1320
1233 1321
1234 RangeBoundary RangeBoundary::IntersectionMin(RangeBoundary a, RangeBoundary b) { 1322 RangeBoundary RangeBoundary::IntersectionMin(RangeBoundary a, RangeBoundary b) {
1235 ASSERT(!a.IsPositiveInfinity() && !b.IsPositiveInfinity()); 1323 ASSERT(!a.IsPositiveInfinity() && !b.IsPositiveInfinity());
1236 ASSERT(!a.IsUnknown() && !b.IsUnknown()); 1324 ASSERT(!a.IsUnknown() && !b.IsUnknown());
1237 1325
1238 if (a.Equals(b)) { 1326 if (a.Equals(b)) {
1239 return a; 1327 return a;
1240 } 1328 }
1241 1329
1242 if (a.IsSmiMinimumOrBelow()) { 1330 if (a.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) {
1243 return b; 1331 return b;
1244 } else if (b.IsSmiMinimumOrBelow()) { 1332 } else if (b.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) {
1245 return a; 1333 return a;
1246 } 1334 }
1247 1335
1248 if (CanonicalizeForComparison(&a, 1336 if (CanonicalizeForComparison(&a,
1249 &b, 1337 &b,
1250 &CanonicalizeMinBoundary, 1338 &CanonicalizeMinBoundary,
1251 RangeBoundary::NegativeInfinity())) { 1339 RangeBoundary::NegativeInfinity())) {
1252 return (a.offset() >= b.offset()) ? a : b; 1340 return (a.offset() >= b.offset()) ? a : b;
1253 } 1341 }
1254 1342
1255 const int64_t inf_a = a.SmiLowerBound(); 1343 const int64_t inf_a = a.SmiLowerBound();
1256 const int64_t inf_b = b.SmiLowerBound(); 1344 const int64_t inf_b = b.SmiLowerBound();
1257 1345
1258 return (inf_a >= inf_b) ? a : b; 1346 return (inf_a >= inf_b) ? a : b;
1259 } 1347 }
1260 1348
1261 1349
1262 RangeBoundary RangeBoundary::IntersectionMax(RangeBoundary a, RangeBoundary b) { 1350 RangeBoundary RangeBoundary::IntersectionMax(RangeBoundary a, RangeBoundary b) {
1263 ASSERT(!a.IsNegativeInfinity() && !b.IsNegativeInfinity()); 1351 ASSERT(!a.IsNegativeInfinity() && !b.IsNegativeInfinity());
1264 ASSERT(!a.IsUnknown() && !b.IsUnknown()); 1352 ASSERT(!a.IsUnknown() && !b.IsUnknown());
1265 1353
1266 if (a.Equals(b)) { 1354 if (a.Equals(b)) {
1267 return a; 1355 return a;
1268 } 1356 }
1269 1357
1270 if (a.IsSmiMaximumOrAbove()) { 1358 if (a.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) {
1271 return b; 1359 return b;
1272 } else if (b.IsSmiMaximumOrAbove()) { 1360 } else if (b.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) {
1273 return a; 1361 return a;
1274 } 1362 }
1275 1363
1276 if (CanonicalizeForComparison(&a, 1364 if (CanonicalizeForComparison(&a,
1277 &b, 1365 &b,
1278 &CanonicalizeMaxBoundary, 1366 &CanonicalizeMaxBoundary,
1279 RangeBoundary::PositiveInfinity())) { 1367 RangeBoundary::PositiveInfinity())) {
1280 return (a.offset() <= b.offset()) ? a : b; 1368 return (a.offset() <= b.offset()) ? a : b;
1281 } 1369 }
1282 1370
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1543 ASSERT(right_range != NULL); 1631 ASSERT(right_range != NULL);
1544 ASSERT(result_min != NULL); 1632 ASSERT(result_min != NULL);
1545 ASSERT(result_max != NULL); 1633 ASSERT(result_max != NULL);
1546 1634
1547 const int64_t left_max = ConstantAbsMax(left_range); 1635 const int64_t left_max = ConstantAbsMax(left_range);
1548 const int64_t right_max = ConstantAbsMax(right_range); 1636 const int64_t right_max = ConstantAbsMax(right_range);
1549 if ((left_max <= -kSmiMin) && (right_max <= -kSmiMin) && 1637 if ((left_max <= -kSmiMin) && (right_max <= -kSmiMin) &&
1550 ((left_max == 0) || (right_max <= kMaxInt64 / left_max))) { 1638 ((left_max == 0) || (right_max <= kMaxInt64 / left_max))) {
1551 // Product of left and right max values stays in 64 bit range. 1639 // Product of left and right max values stays in 64 bit range.
1552 const int64_t mul_max = left_max * right_max; 1640 const int64_t mul_max = left_max * right_max;
1553 if (Smi::IsValid(mul_max) && Smi::IsValid(-mul_max)) { 1641 const int64_t r_min =
1554 const int64_t r_min = 1642 OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -mul_max;
1555 OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -mul_max; 1643 *result_min = RangeBoundary::FromConstant(r_min);
1556 *result_min = RangeBoundary::FromConstant(r_min); 1644 const int64_t r_max =
1557 const int64_t r_max = 1645 OnlyNegativeOrZero(*left_range, *right_range) ? 0 : mul_max;
1558 OnlyNegativeOrZero(*left_range, *right_range) ? 0 : mul_max; 1646 *result_max = RangeBoundary::FromConstant(r_max);
1559 *result_max = RangeBoundary::FromConstant(r_max); 1647 return true;
1560 return true;
1561 }
1562 } 1648 }
1563 1649
1564 // TODO(vegorov): handle mixed sign case that leads to (-Infinity, 0] range. 1650 // TODO(vegorov): handle mixed sign case that leads to (-Infinity, 0] range.
1565 if (OnlyPositiveOrZero(*left_range, *right_range) || 1651 if (OnlyPositiveOrZero(*left_range, *right_range) ||
1566 OnlyNegativeOrZero(*left_range, *right_range)) { 1652 OnlyNegativeOrZero(*left_range, *right_range)) {
1567 *result_min = RangeBoundary::FromConstant(0); 1653 *result_min = RangeBoundary::FromConstant(0);
1568 *result_max = RangeBoundary::PositiveInfinity(); 1654 *result_max = RangeBoundary::PositiveInfinity();
1569 return true; 1655 return true;
1570 } 1656 }
1571 1657
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1657 } 1743 }
1658 *range_ = range; 1744 *range_ = range;
1659 } 1745 }
1660 1746
1661 1747
1662 void Definition::InferRange(RangeAnalysis* analysis, Range* range) { 1748 void Definition::InferRange(RangeAnalysis* analysis, Range* range) {
1663 if (Type()->ToCid() == kSmiCid) { 1749 if (Type()->ToCid() == kSmiCid) {
1664 *range = Range::Full(RangeBoundary::kRangeBoundarySmi); 1750 *range = Range::Full(RangeBoundary::kRangeBoundarySmi);
1665 } else if (IsMintDefinition()) { 1751 } else if (IsMintDefinition()) {
1666 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64); 1752 *range = Range::Full(RangeBoundary::kRangeBoundaryInt64);
1753 } else if (IsInt32Definition()) {
1754 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32);
1667 } else { 1755 } else {
1668 // Only Smi and Mint supported. 1756 // Only Smi and Mint supported.
1669 UNREACHABLE(); 1757 UNREACHABLE();
1670 } 1758 }
1671 } 1759 }
1672 1760
1673 1761
1674 static bool DependsOnSymbol(const RangeBoundary& a, Definition* symbol) { 1762 static bool DependsOnSymbol(const RangeBoundary& a, Definition* symbol) {
1675 return a.IsSymbol() && (UnwrapConstraint(a.symbol()) == symbol); 1763 return a.IsSymbol() && (UnwrapConstraint(a.symbol()) == symbol);
1676 } 1764 }
1677 1765
1678 1766
1679 // Given the range and definition update the range so that 1767 // Given the range and definition update the range so that
1680 // it covers both original range and defintions range. 1768 // it covers both original range and defintions range.
1681 // 1769 //
1682 // The following should also hold: 1770 // The following should also hold:
1683 // 1771 //
1684 // [_|_, _|_] U a = a U [_|_, _|_] = a 1772 // [_|_, _|_] U a = a U [_|_, _|_] = a
1685 // 1773 //
1686 static void Join(Range* range, Definition* defn, const Range* defn_range) { 1774 static void Join(Range* range,
1775 Definition* defn,
1776 const Range* defn_range,
1777 RangeBoundary::RangeSize size) {
1687 if (Range::IsUnknown(defn_range)) { 1778 if (Range::IsUnknown(defn_range)) {
1688 return; 1779 return;
1689 } 1780 }
1690 1781
1691 if (Range::IsUnknown(range)) { 1782 if (Range::IsUnknown(range)) {
1692 *range = *defn_range; 1783 *range = *defn_range;
1693 return; 1784 return;
1694 } 1785 }
1695 1786
1696 Range other = *defn_range; 1787 Range other = *defn_range;
1697 1788
1698 // Handle patterns where range already depends on defn as a symbol: 1789 // Handle patterns where range already depends on defn as a symbol:
1699 // 1790 //
1700 // (..., S+o] U range(S) and [S+o, ...) U range(S) 1791 // (..., S+o] U range(S) and [S+o, ...) U range(S)
1701 // 1792 //
1702 // To improve precision of the computed join use [S, S] instead of 1793 // To improve precision of the computed join use [S, S] instead of
1703 // using range(S). It will be canonicalized away by JoinMin/JoinMax 1794 // using range(S). It will be canonicalized away by JoinMin/JoinMax
1704 // functions. 1795 // functions.
1705 Definition* unwrapped = UnwrapConstraint(defn); 1796 Definition* unwrapped = UnwrapConstraint(defn);
1706 if (DependsOnSymbol(range->min(), unwrapped) || 1797 if (DependsOnSymbol(range->min(), unwrapped) ||
1707 DependsOnSymbol(range->max(), unwrapped)) { 1798 DependsOnSymbol(range->max(), unwrapped)) {
1708 other = Range(RangeBoundary::FromDefinition(defn, 0), 1799 other = Range(RangeBoundary::FromDefinition(defn, 0),
1709 RangeBoundary::FromDefinition(defn, 0)); 1800 RangeBoundary::FromDefinition(defn, 0));
1710 } 1801 }
1711 1802
1712 // First try to compare ranges based on their upper and lower bounds. 1803 // First try to compare ranges based on their upper and lower bounds.
1713 const int64_t inf_range = range->min().SmiLowerBound(); 1804 const int64_t inf_range = range->min().LowerBound(size);
1714 const int64_t inf_other = other.min().SmiLowerBound(); 1805 const int64_t inf_other = other.min().LowerBound(size);
1715 const int64_t sup_range = range->max().SmiUpperBound(); 1806 const int64_t sup_range = range->max().UpperBound(size);
1716 const int64_t sup_other = other.max().SmiUpperBound(); 1807 const int64_t sup_other = other.max().UpperBound(size);
1717 1808
1718 if (sup_range <= inf_other) { 1809 if (sup_range <= inf_other) {
1719 // The range is fully below defn's range. Keep the minimum and 1810 // The range is fully below defn's range. Keep the minimum and
1720 // expand the maximum. 1811 // expand the maximum.
1721 range->set_max(other.max()); 1812 range->set_max(other.max());
1722 } else if (sup_other <= inf_range) { 1813 } else if (sup_other <= inf_range) {
1723 // The range is fully above defn's range. Keep the maximum and 1814 // The range is fully above defn's range. Keep the maximum and
1724 // expand the minimum. 1815 // expand the minimum.
1725 range->set_min(other.min()); 1816 range->set_min(other.min());
1726 } else { 1817 } else {
1727 // Can't compare ranges as whole. Join minimum and maximum separately. 1818 // Can't compare ranges as whole. Join minimum and maximum separately.
1728 *range = Range(RangeBoundary::JoinMin(range->min(), other.min()), 1819 *range = Range(RangeBoundary::JoinMin(range->min(), other.min(), size),
1729 RangeBoundary::JoinMax(range->max(), other.max())); 1820 RangeBoundary::JoinMax(range->max(), other.max(), size));
1730 } 1821 }
1731 } 1822 }
1732 1823
1733 1824
1734 // When assigning range to a phi we must take care to avoid self-reference 1825 // When assigning range to a phi we must take care to avoid self-reference
1735 // cycles when phi's range depends on the phi itself. 1826 // cycles when phi's range depends on the phi itself.
1736 // To prevent such cases we impose additional restriction on symbols that 1827 // To prevent such cases we impose additional restriction on symbols that
1737 // can be used as boundaries for phi's range: they must dominate 1828 // can be used as boundaries for phi's range: they must dominate
1738 // phi's definition. 1829 // phi's definition.
1739 static RangeBoundary EnsureAcyclicSymbol(BlockEntryInstr* phi_block, 1830 static RangeBoundary EnsureAcyclicSymbol(BlockEntryInstr* phi_block,
1740 const RangeBoundary& a, 1831 const RangeBoundary& a,
1741 const RangeBoundary& limit) { 1832 const RangeBoundary& limit) {
1742 if (!a.IsSymbol() || a.symbol()->GetBlock()->Dominates(phi_block)) { 1833 if (!a.IsSymbol() || a.symbol()->GetBlock()->Dominates(phi_block)) {
1743 return a; 1834 return a;
1744 } 1835 }
1745 1836
1746 // Symbol does not dominate phi. Try unwrapping constraint and check again. 1837 // Symbol does not dominate phi. Try unwrapping constraint and check again.
1747 Definition* unwrapped = UnwrapConstraint(a.symbol()); 1838 Definition* unwrapped = UnwrapConstraint(a.symbol());
1748 if ((unwrapped != a.symbol()) && 1839 if ((unwrapped != a.symbol()) &&
1749 unwrapped->GetBlock()->Dominates(phi_block)) { 1840 unwrapped->GetBlock()->Dominates(phi_block)) {
1750 return RangeBoundary::FromDefinition(unwrapped, a.offset()); 1841 return RangeBoundary::FromDefinition(unwrapped, a.offset());
1751 } 1842 }
1752 1843
1753 return limit; 1844 return limit;
1754 } 1845 }
1755 1846
1756 1847
1757 void PhiInstr::InferRange(RangeAnalysis* analysis, Range* range) { 1848 void PhiInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1758 ASSERT(Type()->ToCid() == kSmiCid); 1849 ASSERT((Type()->ToCid() == kSmiCid) || (representation() == kUnboxedInt32));
1850 const RangeBoundary::RangeSize size = (Type()->ToCid() == kSmiCid) ?
1851 RangeBoundary::kRangeBoundarySmi : RangeBoundary::kRangeBoundaryInt32;
1759 for (intptr_t i = 0; i < InputCount(); i++) { 1852 for (intptr_t i = 0; i < InputCount(); i++) {
1760 Value* input = InputAt(i); 1853 Value* input = InputAt(i);
1761 Join(range, input->definition(), analysis->GetSmiRange(input)); 1854 const Range* input_range = (size == RangeBoundary::kRangeBoundarySmi) ?
1855 analysis->GetSmiRange(input) : input->definition()->range();
1856 Join(range,
1857 input->definition(), input_range, size);
1762 } 1858 }
1763 1859
1764 BlockEntryInstr* phi_block = GetBlock(); 1860 BlockEntryInstr* phi_block = GetBlock();
1765 range->set_min(EnsureAcyclicSymbol( 1861 range->set_min(EnsureAcyclicSymbol(
1766 phi_block, range->min(), RangeBoundary::MinSmi())); 1862 phi_block, range->min(), RangeBoundary::MinSmi()));
1767 range->set_max(EnsureAcyclicSymbol( 1863 range->set_max(EnsureAcyclicSymbol(
1768 phi_block, range->max(), RangeBoundary::MaxSmi())); 1864 phi_block, range->max(), RangeBoundary::MaxSmi()));
1769 } 1865 }
1770 1866
1771 1867
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1912 // Calculate overflowed status before clamping. 2008 // Calculate overflowed status before clamping.
1913 const bool overflowed = range->min().LowerBound().OverflowedSmi() || 2009 const bool overflowed = range->min().LowerBound().OverflowedSmi() ||
1914 range->max().UpperBound().OverflowedSmi(); 2010 range->max().UpperBound().OverflowedSmi();
1915 set_overflow(overflowed); 2011 set_overflow(overflowed);
1916 2012
1917 // Clamp value to be within smi range. 2013 // Clamp value to be within smi range.
1918 range->Clamp(RangeBoundary::kRangeBoundarySmi); 2014 range->Clamp(RangeBoundary::kRangeBoundarySmi);
1919 } 2015 }
1920 2016
1921 2017
2018 void BoxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2019 const Range* value_range = value()->definition()->range();
2020 if (!Range::IsUnknown(value_range)) {
2021 *range = *value_range;
2022 }
2023 }
2024
2025
2026 void UnboxInt32Instr::InferRange(RangeAnalysis* analysis, Range* range) {
2027 if (value()->definition()->Type()->ToCid() == kSmiCid) {
2028 const Range* value_range = analysis->GetSmiRange(value());
2029 if (!Range::IsUnknown(value_range)) {
2030 *range = *value_range;
2031 }
2032 } else if (value()->definition()->IsMintDefinition() ||
2033 value()->definition()->IsInt32Definition()) {
2034 const Range* value_range = value()->definition()->range();
2035 if (!Range::IsUnknown(value_range)) {
2036 *range = *value_range;
2037 }
2038 } else if (value()->Type()->ToCid() == kSmiCid) {
2039 *range = Range::Full(RangeBoundary::kRangeBoundarySmi);
2040 } else {
2041 *range = Range::Full(RangeBoundary::kRangeBoundaryInt32);
2042 }
2043 }
2044
2045
2046 void UnboxedIntConverterInstr::InferRange(RangeAnalysis* analysis,
2047 Range* range) {
2048 ASSERT((from() == kUnboxedInt32) ||
2049 (from() == kUnboxedMint) ||
2050 (from() == kUnboxedUint32));
2051 ASSERT((to() == kUnboxedInt32) ||
2052 (to() == kUnboxedMint) ||
2053 (to() == kUnboxedUint32));
2054 const Range* value_range = value()->definition()->range();
2055 if (Range::IsUnknown(value_range)) {
2056 return;
2057 }
2058
2059 if (to() == kUnboxedUint32) {
2060 // TODO(vegorov): improve range information for unboxing to Uint32.
2061 *range = Range(
2062 RangeBoundary::FromConstant(0),
2063 RangeBoundary::FromConstant(static_cast<int64_t>(kMaxUint32)));
2064 } else {
2065 *range = *value_range;
2066 if (to() == kUnboxedInt32) {
2067 range->Clamp(RangeBoundary::kRangeBoundaryInt32);
2068 }
2069 }
2070 }
2071
2072
2073 void BinaryInt32OpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
2074 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the
2075 // right and a non-constant on the left.
2076 Definition* left_defn = left()->definition();
2077
2078 const Range* left_range = analysis->GetSmiRange(left());
2079 const Range* right_range = analysis->GetSmiRange(right());
2080
2081 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
2082 return;
2083 }
2084
2085 Range::BinaryOp(op_kind(),
2086 left_range,
2087 right_range,
2088 left_defn,
2089 range);
2090 ASSERT(!Range::IsUnknown(range));
2091
2092 // Calculate overflowed status before clamping.
2093 set_overflow(!range->Fits(RangeBoundary::kRangeBoundaryInt32));
2094
2095 // Clamp value to be within smi range.
2096 range->Clamp(RangeBoundary::kRangeBoundaryInt32);
2097 }
2098
1922 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2099 void BinaryMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1923 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on 2100 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on
1924 // the right and a non-constant on the left. 2101 // the right and a non-constant on the left.
1925 Definition* left_defn = left()->definition(); 2102 Definition* left_defn = left()->definition();
1926 2103
1927 const Range* left_range = left_defn->range(); 2104 const Range* left_range = left_defn->range();
1928 const Range* right_range = right()->definition()->range(); 2105 const Range* right_range = right()->definition()->range();
1929 2106
1930 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) { 2107 if (Range::IsUnknown(left_range) || Range::IsUnknown(right_range)) {
1931 return; 2108 return;
1932 } 2109 }
1933 2110
1934 Range::BinaryOp(op_kind(), 2111 Range::BinaryOp(op_kind(),
1935 left_range, 2112 left_range,
1936 right_range, 2113 right_range,
1937 left_defn, 2114 left_defn,
1938 range); 2115 range);
1939 ASSERT(!Range::IsUnknown(range)); 2116 ASSERT(!Range::IsUnknown(range));
1940 2117
1941 // Calculate overflowed status before clamping. 2118 // Calculate overflowed status before clamping.
1942 const bool overflowed = range->min().LowerBound().OverflowedMint() || 2119 set_can_overflow(!range->Fits(RangeBoundary::kRangeBoundaryInt64));
1943 range->max().UpperBound().OverflowedMint();
1944 set_can_overflow(overflowed);
1945 2120
1946 // Clamp value to be within mint range. 2121 // Clamp value to be within mint range.
1947 range->Clamp(RangeBoundary::kRangeBoundaryInt64); 2122 range->Clamp(RangeBoundary::kRangeBoundaryInt64);
1948 } 2123 }
1949 2124
1950 2125
1951 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2126 void ShiftMintOpInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1952 Definition* left_defn = left()->definition(); 2127 Definition* left_defn = left()->definition();
1953 2128
1954 const Range* left_range = left_defn->range(); 2129 const Range* left_range = left_defn->range();
(...skipping 16 matching lines...) Expand all
1971 set_can_overflow(overflowed); 2146 set_can_overflow(overflowed);
1972 2147
1973 // Clamp value to be within mint range. 2148 // Clamp value to be within mint range.
1974 range->Clamp(RangeBoundary::kRangeBoundaryInt64); 2149 range->Clamp(RangeBoundary::kRangeBoundaryInt64);
1975 } 2150 }
1976 2151
1977 2152
1978 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2153 void BoxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1979 const Range* input_range = value()->definition()->range(); 2154 const Range* input_range = value()->definition()->range();
1980 if (input_range != NULL) { 2155 if (input_range != NULL) {
1981 bool is_smi = !input_range->min().LowerBound().OverflowedSmi() && 2156 bool is_smi = input_range->Fits(RangeBoundary::kRangeBoundarySmi);
1982 !input_range->max().UpperBound().OverflowedSmi();
1983 set_is_smi(is_smi); 2157 set_is_smi(is_smi);
1984 // The output range is the same as the input range. 2158 // The output range is the same as the input range.
1985 *range = *input_range; 2159 *range = *input_range;
1986 } 2160 }
1987 } 2161 }
1988 2162
1989 2163
1990 void UnboxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) { 2164 void UnboxIntegerInstr::InferRange(RangeAnalysis* analysis, Range* range) {
1991 const Range* value_range = value()->definition()->range(); 2165 const Range* value_range = value()->definition()->range();
1992 if (value_range != NULL) { 2166 if (value_range != NULL) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
2044 } 2218 }
2045 } while (CanonicalizeMaxBoundary(&max) || 2219 } while (CanonicalizeMaxBoundary(&max) ||
2046 CanonicalizeMinBoundary(&canonical_length)); 2220 CanonicalizeMinBoundary(&canonical_length));
2047 2221
2048 // Failed to prove that maximum is bounded with array length. 2222 // Failed to prove that maximum is bounded with array length.
2049 return false; 2223 return false;
2050 } 2224 }
2051 2225
2052 2226
2053 } // namespace dart 2227 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698