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

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

Issue 328503003: Extend Range analysis to 64-bit range and mint operations (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/intermediate_language.h" 5 #include "vm/intermediate_language.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/bit_vector.h" 8 #include "vm/bit_vector.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 2431 matching lines...) Expand 10 before | Expand all | Expand 10 after
2442 intptr_t use_index = instr->env()->Length(); // Start index after inner. 2442 intptr_t use_index = instr->env()->Length(); // Start index after inner.
2443 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) { 2443 for (Environment::DeepIterator it(copy); !it.Done(); it.Advance()) {
2444 Value* value = it.CurrentValue(); 2444 Value* value = it.CurrentValue();
2445 value->set_instruction(instr); 2445 value->set_instruction(instr);
2446 value->set_use_index(use_index++); 2446 value->set_use_index(use_index++);
2447 value->definition()->AddEnvUse(value); 2447 value->definition()->AddEnvUse(value);
2448 } 2448 }
2449 } 2449 }
2450 2450
2451 2451
2452 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, intptr_t offs) { 2452 RangeBoundary RangeBoundary::FromDefinition(Definition* defn, int64_t offs) {
2453 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) { 2453 if (defn->IsConstant() && defn->AsConstant()->value().IsSmi()) {
2454 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs); 2454 return FromConstant(Smi::Cast(defn->AsConstant()->value()).Value() + offs);
2455 } 2455 }
2456 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs); 2456 return RangeBoundary(kSymbol, reinterpret_cast<intptr_t>(defn), offs);
2457 } 2457 }
2458 2458
2459 2459
2460 RangeBoundary RangeBoundary::LowerBound() const { 2460 RangeBoundary RangeBoundary::LowerBound() const {
2461 if (IsNegativeInfinity()) return *this; 2461 if (IsInfinity()) {
2462 return NegativeInfinity();
2463 }
2462 if (IsConstant()) return *this; 2464 if (IsConstant()) return *this;
2463 return Add(Range::ConstantMin(symbol()->range()), 2465 return Add(Range::ConstantMin(symbol()->range()),
2464 RangeBoundary::FromConstant(offset_), 2466 RangeBoundary::FromConstant(offset_),
2465 NegativeInfinity()); 2467 NegativeInfinity());
2466 } 2468 }
2467 2469
2468 2470
2469 RangeBoundary RangeBoundary::UpperBound() const { 2471 RangeBoundary RangeBoundary::UpperBound() const {
2470 if (IsPositiveInfinity()) return *this; 2472 if (IsInfinity()) {
2473 return PositiveInfinity();
2474 }
2471 if (IsConstant()) return *this; 2475 if (IsConstant()) return *this;
2472 return Add(Range::ConstantMax(symbol()->range()), 2476 return Add(Range::ConstantMax(symbol()->range()),
2473 RangeBoundary::FromConstant(offset_), 2477 RangeBoundary::FromConstant(offset_),
2474 PositiveInfinity()); 2478 PositiveInfinity());
2475 } 2479 }
2476 2480
2477 2481
2482 RangeBoundary RangeBoundary::Add(const RangeBoundary& a,
2483 const RangeBoundary& b,
2484 const RangeBoundary& overflow) {
2485 ASSERT(a.IsConstant() && b.IsConstant());
2486
2487 if (Utils::WillAddOverflow(a.ConstantValue(), b.ConstantValue())) {
2488 return overflow;
2489 }
2490
2491 int64_t result = a.ConstantValue() + b.ConstantValue();
2492
2493 return RangeBoundary::FromConstant(result);
2494 }
2495
2496
2497 RangeBoundary RangeBoundary::Sub(const RangeBoundary& a,
2498 const RangeBoundary& b,
2499 const RangeBoundary& overflow) {
2500 ASSERT(a.IsConstant() && b.IsConstant());
2501
2502 if (Utils::WillSubOverflow(a.ConstantValue(), b.ConstantValue())) {
2503 return overflow;
2504 }
2505
2506 int64_t result = a.ConstantValue() - b.ConstantValue();
2507
2508 return RangeBoundary::FromConstant(result);
2509 }
2510
2511
2512 bool RangeBoundary::SymbolicAdd(const RangeBoundary& a,
2513 const RangeBoundary& b,
2514 RangeBoundary* result) {
2515 if (a.IsSymbol() && b.IsConstant()) {
2516 if (Utils::WillAddOverflow(a.offset(), b.ConstantValue())) {
2517 return false;
2518 }
2519
2520 const int64_t offset = a.offset() + b.ConstantValue();
2521
2522 *result = RangeBoundary::FromDefinition(a.symbol(), offset);
2523 return true;
2524 } else if (b.IsSymbol() && a.IsConstant()) {
2525 return SymbolicAdd(b, a, result);
2526 }
2527 return false;
2528 }
2529
2530
2531 bool RangeBoundary::SymbolicSub(const RangeBoundary& a,
2532 const RangeBoundary& b,
2533 RangeBoundary* result) {
2534 if (a.IsSymbol() && b.IsConstant()) {
2535 if (Utils::WillSubOverflow(a.offset(), b.ConstantValue())) {
2536 return false;
2537 }
2538
2539 const int64_t offset = a.offset() - b.ConstantValue();
2540
2541 *result = RangeBoundary::FromDefinition(a.symbol(), offset);
2542 return true;
2543 }
2544 return false;
2545 }
2546
2547
2478 static Definition* UnwrapConstraint(Definition* defn) { 2548 static Definition* UnwrapConstraint(Definition* defn) {
2479 while (defn->IsConstraint()) { 2549 while (defn->IsConstraint()) {
2480 defn = defn->AsConstraint()->value()->definition(); 2550 defn = defn->AsConstraint()->value()->definition();
2481 } 2551 }
2482 return defn; 2552 return defn;
2483 } 2553 }
2484 2554
2485 2555
2486 static bool AreEqualDefinitions(Definition* a, Definition* b) { 2556 static bool AreEqualDefinitions(Definition* a, Definition* b) {
2487 a = UnwrapConstraint(a); 2557 a = UnwrapConstraint(a);
2488 b = UnwrapConstraint(b); 2558 b = UnwrapConstraint(b);
2489 return (a == b) || 2559 return (a == b) ||
2490 (a->AllowsCSE() && 2560 (a->AllowsCSE() &&
2491 a->Dependencies().IsNone() && 2561 a->Dependencies().IsNone() &&
2492 b->AllowsCSE() && 2562 b->AllowsCSE() &&
2493 b->Dependencies().IsNone() && 2563 b->Dependencies().IsNone() &&
2494 a->Equals(b)); 2564 a->Equals(b));
2495 } 2565 }
2496 2566
2497 2567
2498 // Returns true if two range boundaries refer to the same symbol. 2568 // Returns true if two range boundaries refer to the same symbol.
2499 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) { 2569 static bool DependOnSameSymbol(const RangeBoundary& a, const RangeBoundary& b) {
2500 return a.IsSymbol() && b.IsSymbol() && 2570 return a.IsSymbol() && b.IsSymbol() &&
2501 AreEqualDefinitions(a.symbol(), b.symbol()); 2571 AreEqualDefinitions(a.symbol(), b.symbol());
2502 } 2572 }
2503 2573
2504 2574
2505 // Returns true if range has a least specific minimum value. 2575 bool RangeBoundary::Equals(const RangeBoundary& other) const {
2506 static bool IsMinSmi(Range* range) { 2576 if (IsConstant() && other.IsConstant()) {
2507 return (range == NULL) || 2577 return ConstantValue() == other.ConstantValue();
2508 (range->min().IsConstant() && 2578 } else if (IsInfinity() && other.IsInfinity()) {
2509 (range->min().value() <= Smi::kMinValue)); 2579 return kind() == other.kind();
2580 } else if (IsSymbol() && other.IsSymbol()) {
2581 return (offset() == other.offset()) && DependOnSameSymbol(*this, other);
2582 } else if (IsUnknown() && other.IsUnknown()) {
2583 return true;
2584 }
2585 return false;
2510 } 2586 }
2511 2587
2512 2588
2513 // Returns true if range has a least specific maximium value. 2589 RangeBoundary RangeBoundary::Shl(const RangeBoundary& value_boundary,
2514 static bool IsMaxSmi(Range* range) { 2590 int64_t shift_count,
2515 return (range == NULL) || 2591 const RangeBoundary& overflow) {
2516 (range->max().IsConstant() && 2592 ASSERT(value_boundary.IsConstant());
2517 (range->max().value() >= Smi::kMaxValue)); 2593 ASSERT(shift_count >= 0);
2518 } 2594 int64_t limit = 64 - shift_count;
2595 int64_t value = static_cast<int64_t>(value_boundary.ConstantValue());
2519 2596
2597 if ((value == 0) ||
2598 (shift_count == 0) ||
2599 ((limit > 0) && (Utils::IsInt(limit, value)))) {
2600 // Result stays in 64 bit range.
2601 int64_t result = value << shift_count;
2602 return Smi::IsValid64(result) ? RangeBoundary(result) : overflow;
2603 }
2520 2604
2521 // Returns true if two range boundaries can be proven to be equal. 2605 return overflow;
2522 static bool IsEqual(const RangeBoundary& a, const RangeBoundary& b) {
2523 if (a.IsConstant() && b.IsConstant()) {
2524 return a.value() == b.value();
2525 } else if (a.IsSymbol() && b.IsSymbol()) {
2526 return (a.offset() == b.offset()) && DependOnSameSymbol(a, b);
2527 } else {
2528 return false;
2529 }
2530 } 2606 }
2531 2607
2532 2608
2533 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a, 2609 static RangeBoundary CanonicalizeBoundary(const RangeBoundary& a,
2534 const RangeBoundary& overflow) { 2610 const RangeBoundary& overflow) {
2535 if (a.IsConstant() || a.IsNegativeInfinity() || a.IsPositiveInfinity()) { 2611 if (a.IsConstant() || a.IsInfinity()) {
2536 return a; 2612 return a;
2537 } 2613 }
2538 2614
2539 intptr_t offset = a.offset(); 2615 int64_t offset = a.offset();
2540 Definition* symbol = a.symbol(); 2616 Definition* symbol = a.symbol();
2541 2617
2542 bool changed; 2618 bool changed;
2543 do { 2619 do {
2544 changed = false; 2620 changed = false;
2545 if (symbol->IsConstraint()) { 2621 if (symbol->IsConstraint()) {
2546 symbol = symbol->AsConstraint()->value()->definition(); 2622 symbol = symbol->AsConstraint()->value()->definition();
2547 changed = true; 2623 changed = true;
2548 } else if (symbol->IsBinarySmiOp()) { 2624 } else if (symbol->IsBinarySmiOp()) {
2549 BinarySmiOpInstr* op = symbol->AsBinarySmiOp(); 2625 BinarySmiOpInstr* op = symbol->AsBinarySmiOp();
2550 Definition* left = op->left()->definition(); 2626 Definition* left = op->left()->definition();
2551 Definition* right = op->right()->definition(); 2627 Definition* right = op->right()->definition();
2552 switch (op->op_kind()) { 2628 switch (op->op_kind()) {
2553 case Token::kADD: 2629 case Token::kADD:
2554 if (right->IsConstant()) { 2630 if (right->IsConstant()) {
2555 offset += Smi::Cast(right->AsConstant()->value()).Value(); 2631 int64_t rhs = Smi::Cast(right->AsConstant()->value()).Value();
2632 if (Utils::WillAddOverflow(offset, rhs)) {
2633 return overflow;
2634 }
2635 offset += rhs;
2556 symbol = left; 2636 symbol = left;
2557 changed = true; 2637 changed = true;
2558 } else if (left->IsConstant()) { 2638 } else if (left->IsConstant()) {
2559 offset += Smi::Cast(left->AsConstant()->value()).Value(); 2639 int64_t rhs = Smi::Cast(left->AsConstant()->value()).Value();
2640 if (Utils::WillAddOverflow(offset, rhs)) {
2641 return overflow;
2642 }
2643 offset += rhs;
2560 symbol = right; 2644 symbol = right;
2561 changed = true; 2645 changed = true;
2562 } 2646 }
2563 break; 2647 break;
2564 2648
2565 case Token::kSUB: 2649 case Token::kSUB:
2566 if (right->IsConstant()) { 2650 if (right->IsConstant()) {
2567 offset -= Smi::Cast(right->AsConstant()->value()).Value(); 2651 int64_t rhs = Smi::Cast(right->AsConstant()->value()).Value();
2652 if (Utils::WillSubOverflow(offset, rhs)) {
2653 return overflow;
2654 }
2655 offset -= rhs;
2568 symbol = left; 2656 symbol = left;
2569 changed = true; 2657 changed = true;
2570 } 2658 }
2571 break; 2659 break;
2572 2660
2573 default: 2661 default:
2574 break; 2662 break;
2575 } 2663 }
2576 } 2664 }
2577
2578 if (!Smi::IsValid(offset)) return overflow;
2579 } while (changed); 2665 } while (changed);
2580 2666
2581 return RangeBoundary::FromDefinition(symbol, offset); 2667 return RangeBoundary::FromDefinition(symbol, offset);
2582 } 2668 }
2583 2669
2584 2670
2585 static bool CanonicalizeMaxBoundary(RangeBoundary* a) { 2671 static bool CanonicalizeMaxBoundary(RangeBoundary* a) {
2586 if (!a->IsSymbol()) return false; 2672 if (!a->IsSymbol()) return false;
2587 2673
2588 Range* range = a->symbol()->range(); 2674 Range* range = a->symbol()->range();
2589 if ((range == NULL) || !range->max().IsSymbol()) return false; 2675 if ((range == NULL) || !range->max().IsSymbol()) return false;
2590 2676
2591 const intptr_t offset = range->max().offset() + a->offset();
2592 2677
2593 if (!Smi::IsValid(offset)) { 2678 if (Utils::WillAddOverflow(range->max().offset(), a->offset())) {
2594 *a = RangeBoundary::PositiveInfinity(); 2679 *a = RangeBoundary::PositiveInfinity();
2595 return true; 2680 return true;
2596 } 2681 }
2597 2682
2683 const int64_t offset = range->max().offset() + a->offset();
2684
2685
2598 *a = CanonicalizeBoundary( 2686 *a = CanonicalizeBoundary(
2599 RangeBoundary::FromDefinition(range->max().symbol(), offset), 2687 RangeBoundary::FromDefinition(range->max().symbol(), offset),
2600 RangeBoundary::PositiveInfinity()); 2688 RangeBoundary::PositiveInfinity());
2601 2689
2602 return true; 2690 return true;
2603 } 2691 }
2604 2692
2605 2693
2606 static bool CanonicalizeMinBoundary(RangeBoundary* a) { 2694 static bool CanonicalizeMinBoundary(RangeBoundary* a) {
2607 if (!a->IsSymbol()) return false; 2695 if (!a->IsSymbol()) return false;
2608 2696
2609 Range* range = a->symbol()->range(); 2697 Range* range = a->symbol()->range();
2610 if ((range == NULL) || !range->min().IsSymbol()) return false; 2698 if ((range == NULL) || !range->min().IsSymbol()) return false;
2611 2699
2612 const intptr_t offset = range->min().offset() + a->offset(); 2700 if (Utils::WillAddOverflow(range->min().offset(), a->offset())) {
2613 if (!Smi::IsValid(offset)) {
2614 *a = RangeBoundary::NegativeInfinity(); 2701 *a = RangeBoundary::NegativeInfinity();
2615 return true; 2702 return true;
2616 } 2703 }
2617 2704
2705 const int64_t offset = range->min().offset() + a->offset();
2706
2618 *a = CanonicalizeBoundary( 2707 *a = CanonicalizeBoundary(
2619 RangeBoundary::FromDefinition(range->min().symbol(), offset), 2708 RangeBoundary::FromDefinition(range->min().symbol(), offset),
2620 RangeBoundary::NegativeInfinity()); 2709 RangeBoundary::NegativeInfinity());
2621 2710
2622 return true; 2711 return true;
2623 } 2712 }
2624 2713
2625 2714
2626 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b) { 2715 RangeBoundary RangeBoundary::Min(RangeBoundary a, RangeBoundary b,
2716 RangeSize size) {
2717 ASSERT(!(a.IsNegativeInfinity() || b.IsNegativeInfinity()));
2718 ASSERT(!a.IsUnknown() || !b.IsUnknown());
2719 if (a.IsUnknown() && !b.IsUnknown()) {
2720 return b;
2721 }
2722 if (!a.IsUnknown() && b.IsUnknown()) {
2723 return a;
2724 }
2725 if (size == kRangeBoundarySmi) {
2726 if (a.IsSmiMaximumOrAbove() && !b.IsSmiMaximumOrAbove()) {
2727 return b;
2728 }
2729 if (!a.IsSmiMaximumOrAbove() && b.IsSmiMaximumOrAbove()) {
2730 return a;
2731 }
2732 } else {
2733 ASSERT(size == kRangeBoundaryInt64);
2734 if (a.IsMaximumOrAbove() && !b.IsMaximumOrAbove()) {
2735 return b;
2736 }
2737 if (!a.IsMaximumOrAbove() && b.IsMaximumOrAbove()) {
2738 return a;
2739 }
2740 }
2741
2742 if (a.Equals(b)) {
2743 return b;
2744 }
2745
2746 {
2747 RangeBoundary canonical_a =
2748 CanonicalizeBoundary(a, RangeBoundary::PositiveInfinity());
2749 RangeBoundary canonical_b =
2750 CanonicalizeBoundary(b, RangeBoundary::PositiveInfinity());
2751 do {
2752 if (DependOnSameSymbol(canonical_a, canonical_b)) {
2753 a = canonical_a;
2754 b = canonical_b;
2755 break;
2756 }
2757 } while (CanonicalizeMaxBoundary(&canonical_a) ||
2758 CanonicalizeMaxBoundary(&canonical_b));
2759 }
2760
2627 if (DependOnSameSymbol(a, b)) { 2761 if (DependOnSameSymbol(a, b)) {
2628 return (a.offset() <= b.offset()) ? a : b; 2762 return (a.offset() <= b.offset()) ? a : b;
2629 } 2763 }
2630 2764
2631 const intptr_t min_a = a.LowerBound().Clamp().value(); 2765 const int64_t min_a = a.UpperBound().Clamp(size).ConstantValue();
2632 const intptr_t min_b = b.LowerBound().Clamp().value(); 2766 const int64_t min_b = b.UpperBound().Clamp(size).ConstantValue();
2633 2767
2634 return RangeBoundary::FromConstant(Utils::Minimum(min_a, min_b)); 2768 return RangeBoundary::FromConstant(Utils::Minimum(min_a, min_b));
2635 } 2769 }
2636 2770
2637 2771
2638 RangeBoundary RangeBoundary::Max(RangeBoundary a, RangeBoundary b) { 2772 RangeBoundary RangeBoundary::Max(RangeBoundary a, RangeBoundary b,
2639 if (DependOnSameSymbol(a, b)) { 2773 RangeSize size) {
2640 return (a.offset() >= b.offset()) ? a : b; 2774 ASSERT(!(a.IsPositiveInfinity() || b.IsPositiveInfinity()));
2775 ASSERT(!a.IsUnknown() || !b.IsUnknown());
2776 if (a.IsUnknown() && !b.IsUnknown()) {
2777 return b;
2778 }
2779 if (!a.IsUnknown() && b.IsUnknown()) {
2780 return a;
2781 }
2782 if (size == kRangeBoundarySmi) {
2783 if (a.IsSmiMinimumOrBelow() && !b.IsSmiMinimumOrBelow()) {
2784 return b;
2785 }
2786 if (!a.IsSmiMinimumOrBelow() && b.IsSmiMinimumOrBelow()) {
2787 return a;
2788 }
2789 } else {
2790 ASSERT(size == kRangeBoundaryInt64);
2791 if (a.IsMinimumOrBelow() && !b.IsMinimumOrBelow()) {
2792 return b;
2793 }
2794 if (!a.IsMinimumOrBelow() && b.IsMinimumOrBelow()) {
2795 return a;
2796 }
2797 }
2798 if (a.Equals(b)) {
2799 return b;
2641 } 2800 }
2642 2801
2643 const intptr_t max_a = a.UpperBound().Clamp().value(); 2802 {
2644 const intptr_t max_b = b.UpperBound().Clamp().value(); 2803 RangeBoundary canonical_a =
2804 CanonicalizeBoundary(a, RangeBoundary::NegativeInfinity());
2805 RangeBoundary canonical_b =
2806 CanonicalizeBoundary(b, RangeBoundary::NegativeInfinity());
2807
2808 do {
2809 if (DependOnSameSymbol(canonical_a, canonical_b)) {
2810 a = canonical_a;
2811 b = canonical_b;
2812 break;
2813 }
2814 } while (CanonicalizeMinBoundary(&canonical_a) ||
2815 CanonicalizeMinBoundary(&canonical_b));
2816 }
2817
2818 if (DependOnSameSymbol(a, b)) {
2819 return (a.offset() <= b.offset()) ? b : a;
2820 }
2821
2822 const int64_t max_a = a.LowerBound().Clamp(size).ConstantValue();
2823 const int64_t max_b = b.LowerBound().Clamp(size).ConstantValue();
2645 2824
2646 return RangeBoundary::FromConstant(Utils::Maximum(max_a, max_b)); 2825 return RangeBoundary::FromConstant(Utils::Maximum(max_a, max_b));
2647 } 2826 }
2648 2827
2649 2828
2829 int64_t RangeBoundary::ConstantValue() const {
2830 ASSERT(IsConstant());
2831 return value_;
2832 }
2833
2834
2650 void Definition::InferRange() { 2835 void Definition::InferRange() {
2651 ASSERT(Type()->ToCid() == kSmiCid); // Has meaning only for smis. 2836 if (Type()->ToCid() == kSmiCid) {
2652 if (range_ == NULL) { 2837 if (range_ == NULL) {
2653 range_ = Range::Unknown(); 2838 range_ = Range::UnknownSmi();
2839 }
2840 } else if (IsMintDefinition()) {
2841 if (range_ == NULL) {
2842 range_ = Range::Unknown();
2843 }
2844 } else {
2845 // Only Smi and Mint supported.
2846 UNREACHABLE();
2654 } 2847 }
2655 } 2848 }
2656 2849
2657 2850
2658 void ConstantInstr::InferRange() { 2851 void ConstantInstr::InferRange() {
2659 ASSERT(value_.IsSmi()); 2852 if (value_.IsSmi()) {
2660 if (range_ == NULL) { 2853 if (range_ == NULL) {
2661 intptr_t value = Smi::Cast(value_).Value(); 2854 int64_t value = Smi::Cast(value_).Value();
2662 range_ = new Range(RangeBoundary::FromConstant(value), 2855 range_ = new Range(RangeBoundary::FromConstant(value),
2663 RangeBoundary::FromConstant(value)); 2856 RangeBoundary::FromConstant(value));
2857 }
2858 } else if (value_.IsMint()) {
2859 if (range_ == NULL) {
2860 int64_t value = Mint::Cast(value_).value();
2861 range_ = new Range(RangeBoundary::FromConstant(value),
2862 RangeBoundary::FromConstant(value));
2863 }
2864 } else {
2865 // Only Smi and Mint supported.
2866 UNREACHABLE();
2664 } 2867 }
2665 } 2868 }
2666 2869
2870
2871 void UnboxIntegerInstr::InferRange() {
2872 if (range_ == NULL) {
2873 Definition* unboxed = value()->definition();
2874 if (unboxed == NULL) {
Vyacheslav Egorov (Google) 2014/06/19 17:27:29 When is this true? How can we be unboxing "nothing
Cutch 2014/06/19 18:39:35 Switched to an ASSERT.
2875 range_ = Range::Unknown();
2876 return;
2877 }
2878 Range* range = unboxed->range();
2879 if (range == NULL) {
2880 range_ = Range::Unknown();
2881 return;
2882 }
2883 range_ = new Range(range->min(), range->max());
2884 }
2885 }
2886
2667 2887
2668 void ConstraintInstr::InferRange() { 2888 void ConstraintInstr::InferRange() {
2669 Range* value_range = value()->definition()->range(); 2889 Range* value_range = value()->definition()->range();
2670 2890
2671 RangeBoundary min; 2891 RangeBoundary min;
2672 RangeBoundary max; 2892 RangeBoundary max;
2673 2893
2674 if (IsMinSmi(value_range) && !IsMinSmi(constraint())) { 2894 {
2675 min = constraint()->min(); 2895 RangeBoundary value_min = (value_range == NULL) ?
2676 } else if (IsMinSmi(constraint()) && !IsMinSmi(value_range)) { 2896 RangeBoundary() : value_range->min();
2677 min = value_range->min(); 2897 RangeBoundary constraint_min = constraint()->min();
2678 } else if ((value_range != NULL) && 2898 min = RangeBoundary::Max(value_min, constraint_min,
2679 IsEqual(constraint()->min(), value_range->min())) { 2899 RangeBoundary::kRangeBoundarySmi);
Vyacheslav Egorov (Google) 2014/06/19 17:27:29 Add an assertion that value()->definition() is a S
Cutch 2014/06/19 18:39:35 This doesn't work because some Constraints are ins
Vyacheslav Egorov (Google) 2014/06/19 18:42:29 In this case you can see reaching type for value()
Cutch 2014/06/19 20:21:50 Got it. Thanks!
2680 min = constraint()->min();
2681 } else {
2682 if (value_range != NULL) {
2683 RangeBoundary canonical_a =
2684 CanonicalizeBoundary(constraint()->min(),
2685 RangeBoundary::NegativeInfinity());
2686 RangeBoundary canonical_b =
2687 CanonicalizeBoundary(value_range->min(),
2688 RangeBoundary::NegativeInfinity());
2689
2690 do {
2691 if (DependOnSameSymbol(canonical_a, canonical_b)) {
2692 min = (canonical_a.offset() <= canonical_b.offset()) ? canonical_b
2693 : canonical_a;
2694 }
2695 } while (CanonicalizeMinBoundary(&canonical_a) ||
2696 CanonicalizeMinBoundary(&canonical_b));
2697 }
2698
2699 if (min.IsUnknown()) {
2700 min = RangeBoundary::Max(Range::ConstantMin(value_range),
2701 Range::ConstantMin(constraint()));
2702 }
2703 } 2900 }
2704 2901
2705 if (IsMaxSmi(value_range) && !IsMaxSmi(constraint())) { 2902 ASSERT(!min.IsUnknown());
2706 max = constraint()->max();
2707 } else if (IsMaxSmi(constraint()) && !IsMaxSmi(value_range)) {
2708 max = value_range->max();
2709 } else if ((value_range != NULL) &&
2710 IsEqual(constraint()->max(), value_range->max())) {
2711 max = constraint()->max();
2712 } else {
2713 if (value_range != NULL) {
2714 RangeBoundary canonical_b =
2715 CanonicalizeBoundary(value_range->max(),
2716 RangeBoundary::PositiveInfinity());
2717 RangeBoundary canonical_a =
2718 CanonicalizeBoundary(constraint()->max(),
2719 RangeBoundary::PositiveInfinity());
2720 2903
2721 do { 2904 {
2722 if (DependOnSameSymbol(canonical_a, canonical_b)) { 2905 RangeBoundary value_max = (value_range == NULL) ?
2723 max = (canonical_a.offset() <= canonical_b.offset()) ? canonical_a 2906 RangeBoundary() : value_range->max();
2724 : canonical_b; 2907 RangeBoundary constraint_max = constraint()->max();
2725 break; 2908 max = RangeBoundary::Min(value_max, constraint_max,
2726 } 2909 RangeBoundary::kRangeBoundarySmi);
2727 } while (CanonicalizeMaxBoundary(&canonical_a) || 2910 }
2728 CanonicalizeMaxBoundary(&canonical_b));
2729 }
2730 2911
2731 if (max.IsUnknown()) { 2912 ASSERT(!max.IsUnknown());
2732 max = RangeBoundary::Min(Range::ConstantMax(value_range),
2733 Range::ConstantMax(constraint()));
2734 }
2735 }
2736 2913
2737 range_ = new Range(min, max); 2914 range_ = new Range(min, max);
2738 2915
2739 // Mark branches that generate unsatisfiable constraints as constant. 2916 // Mark branches that generate unsatisfiable constraints as constant.
2740 if (target() != NULL && range_->IsUnsatisfiable()) { 2917 if (target() != NULL && range_->IsUnsatisfiable()) {
2741 BranchInstr* branch = 2918 BranchInstr* branch =
2742 target()->PredecessorAt(0)->last_instruction()->AsBranch(); 2919 target()->PredecessorAt(0)->last_instruction()->AsBranch();
2743 if (target() == branch->true_successor()) { 2920 if (target() == branch->true_successor()) {
2744 // True unreachable. 2921 // True unreachable.
2745 if (FLAG_trace_constant_propagation) { 2922 if (FLAG_trace_constant_propagation) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
2798 RangeBoundary::FromConstant(255)); 2975 RangeBoundary::FromConstant(255));
2799 break; 2976 break;
2800 case kTypedDataInt16ArrayCid: 2977 case kTypedDataInt16ArrayCid:
2801 range_ = new Range(RangeBoundary::FromConstant(-32768), 2978 range_ = new Range(RangeBoundary::FromConstant(-32768),
2802 RangeBoundary::FromConstant(32767)); 2979 RangeBoundary::FromConstant(32767));
2803 break; 2980 break;
2804 case kTypedDataUint16ArrayCid: 2981 case kTypedDataUint16ArrayCid:
2805 range_ = new Range(RangeBoundary::FromConstant(0), 2982 range_ = new Range(RangeBoundary::FromConstant(0),
2806 RangeBoundary::FromConstant(65535)); 2983 RangeBoundary::FromConstant(65535));
2807 break; 2984 break;
2985 case kTypedDataInt32ArrayCid:
2986 range_ = new Range(RangeBoundary::FromConstant(kMinInt32),
Vyacheslav Egorov (Google) 2014/06/19 17:27:29 CanDeoptimize() versions of Int32/Uint32 loads sho
Cutch 2014/06/19 18:39:35 Done.
2987 RangeBoundary::FromConstant(kMaxInt32));
2988 break;
2989 case kTypedDataUint32ArrayCid:
2990 range_ = new Range(RangeBoundary::FromConstant(0),
2991 RangeBoundary::FromConstant(kMaxUint32));
2992 break;
2808 case kOneByteStringCid: 2993 case kOneByteStringCid:
2809 range_ = new Range(RangeBoundary::FromConstant(0), 2994 range_ = new Range(RangeBoundary::FromConstant(0),
2810 RangeBoundary::FromConstant(0xFF)); 2995 RangeBoundary::FromConstant(0xFF));
2811 break; 2996 break;
2812 case kTwoByteStringCid: 2997 case kTwoByteStringCid:
2813 range_ = new Range(RangeBoundary::FromConstant(0), 2998 range_ = new Range(RangeBoundary::FromConstant(0),
2814 RangeBoundary::FromConstant(0xFFFF)); 2999 RangeBoundary::FromConstant(0xFFFF));
2815 break; 3000 break;
2816 default: 3001 default:
2817 Definition::InferRange(); 3002 Definition::InferRange();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2912 && !comparison->AsStrictCompare()->needs_number_check(); 3097 && !comparison->AsStrictCompare()->needs_number_check();
2913 } 3098 }
2914 if (comparison->operation_cid() != kSmiCid) { 3099 if (comparison->operation_cid() != kSmiCid) {
2915 // Non-smi comparisons are not supported by if-conversion. 3100 // Non-smi comparisons are not supported by if-conversion.
2916 return false; 3101 return false;
2917 } 3102 }
2918 return is_smi_result; 3103 return is_smi_result;
2919 } 3104 }
2920 3105
2921 3106
2922 void PhiInstr::InferRange() { 3107 void PhiInstr::InferRange() {
Vyacheslav Egorov (Google) 2014/06/19 17:27:30 Assert that Phi is not a Mint?
Cutch 2014/06/19 18:39:35 I've asserted that Phi is a smi.
2923 RangeBoundary new_min; 3108 RangeBoundary new_min;
2924 RangeBoundary new_max; 3109 RangeBoundary new_max;
2925 3110
2926 for (intptr_t i = 0; i < InputCount(); i++) { 3111 for (intptr_t i = 0; i < InputCount(); i++) {
2927 Range* input_range = InputAt(i)->definition()->range(); 3112 Range* input_range = InputAt(i)->definition()->range();
2928 if (input_range == NULL) { 3113 if (input_range == NULL) {
2929 range_ = Range::Unknown(); 3114 range_ = Range::UnknownSmi();
2930 return; 3115 return;
2931 } 3116 }
2932 3117
2933 if (new_min.IsUnknown()) { 3118 if (new_min.IsUnknown()) {
2934 new_min = Range::ConstantMin(input_range); 3119 new_min = Range::ConstantMin(input_range);
2935 } else { 3120 } else {
2936 new_min = RangeBoundary::Min(new_min, Range::ConstantMin(input_range)); 3121 new_min = RangeBoundary::Min(new_min,
3122 Range::ConstantMinSmi(input_range),
3123 RangeBoundary::kRangeBoundarySmi);
2937 } 3124 }
2938 3125
2939 if (new_max.IsUnknown()) { 3126 if (new_max.IsUnknown()) {
2940 new_max = Range::ConstantMax(input_range); 3127 new_max = Range::ConstantMax(input_range);
2941 } else { 3128 } else {
2942 new_max = RangeBoundary::Max(new_max, Range::ConstantMax(input_range)); 3129 new_max = RangeBoundary::Max(new_max,
3130 Range::ConstantMaxSmi(input_range),
3131 RangeBoundary::kRangeBoundarySmi);
2943 } 3132 }
2944 } 3133 }
2945 3134
2946 ASSERT(new_min.IsUnknown() == new_max.IsUnknown()); 3135 ASSERT(new_min.IsUnknown() == new_max.IsUnknown());
2947 if (new_min.IsUnknown()) { 3136 if (new_min.IsUnknown()) {
2948 range_ = Range::Unknown(); 3137 range_ = Range::UnknownSmi();
2949 return; 3138 return;
2950 } 3139 }
2951 3140
2952 range_ = new Range(new_min, new_max); 3141 range_ = new Range(new_min, new_max);
2953 } 3142 }
2954 3143
2955 3144
2956 bool PhiInstr::IsRedundant() const { 3145 bool PhiInstr::IsRedundant() const {
2957 ASSERT(InputCount() > 1); 3146 ASSERT(InputCount() > 1);
2958 Definition* first = InputAt(0)->definition(); 3147 Definition* first = InputAt(0)->definition();
2959 for (intptr_t i = 1; i < InputCount(); ++i) { 3148 for (intptr_t i = 1; i < InputCount(); ++i) {
2960 Definition* def = InputAt(i)->definition(); 3149 Definition* def = InputAt(i)->definition();
2961 if (def != first) return false; 3150 if (def != first) return false;
2962 } 3151 }
2963 return true; 3152 return true;
2964 } 3153 }
2965 3154
2966 3155
2967 static bool SymbolicSub(const RangeBoundary& a,
2968 const RangeBoundary& b,
2969 RangeBoundary* result) {
2970 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) {
2971 const intptr_t offset = a.offset() - b.value();
2972 if (!Smi::IsValid(offset)) return false;
2973
2974 *result = RangeBoundary::FromDefinition(a.symbol(), offset);
2975 return true;
2976 }
2977 return false;
2978 }
2979
2980
2981 static bool SymbolicAdd(const RangeBoundary& a,
2982 const RangeBoundary& b,
2983 RangeBoundary* result) {
2984 if (a.IsSymbol() && b.IsConstant() && !b.Overflowed()) {
2985 const intptr_t offset = a.offset() + b.value();
2986 if (!Smi::IsValid(offset)) return false;
2987
2988 *result = RangeBoundary::FromDefinition(a.symbol(), offset);
2989 return true;
2990 } else if (b.IsSymbol() && a.IsConstant() && !a.Overflowed()) {
2991 const intptr_t offset = b.offset() + a.value();
2992 if (!Smi::IsValid(offset)) return false;
2993
2994 *result = RangeBoundary::FromDefinition(b.symbol(), offset);
2995 return true;
2996 }
2997 return false;
2998 }
2999
3000
3001 static bool IsArrayLength(Definition* defn) { 3156 static bool IsArrayLength(Definition* defn) {
3157 if (defn == NULL) {
3158 return false;
3159 }
3002 LoadFieldInstr* load = defn->AsLoadField(); 3160 LoadFieldInstr* load = defn->AsLoadField();
3003 return (load != NULL) && load->IsImmutableLengthLoad(); 3161 return (load != NULL) && load->IsImmutableLengthLoad();
3004 } 3162 }
3005 3163
3006 3164
3007 static int64_t ConstantAbsMax(const Range* range) {
3008 if (range == NULL) return Smi::kMaxValue;
3009 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).value());
3010 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).value());
3011 return abs_min > abs_max ? abs_min : abs_max;
3012 }
3013
3014
3015 static bool OnlyPositiveOrZero(const Range* a, const Range* b) {
3016 if ((a == NULL) || (b == NULL)) return false;
3017 if (Range::ConstantMin(a).value() < 0) return false;
3018 if (Range::ConstantMin(b).value() < 0) return false;
3019 return true;
3020 }
3021
3022
3023 static bool OnlyNegativeOrZero(const Range* a, const Range* b) {
3024 if ((a == NULL) || (b == NULL)) return false;
3025 if (Range::ConstantMax(a).value() > 0) return false;
3026 if (Range::ConstantMax(b).value() > 0) return false;
3027 return true;
3028 }
3029
3030
3031 void BinarySmiOpInstr::InferRange() { 3165 void BinarySmiOpInstr::InferRange() {
3032 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the 3166 // TODO(vegorov): canonicalize BinarySmiOp to always have constant on the
3033 // right and a non-constant on the left. 3167 // right and a non-constant on the left.
3034 Definition* left_defn = left()->definition(); 3168 Definition* left_defn = left()->definition();
3035 3169
3036 Range* left_range = left_defn->range(); 3170 Range* left_range = left_defn->range();
3037 Range* right_range = right()->definition()->range(); 3171 Range* right_range = right()->definition()->range();
3038 3172
3039 if ((left_range == NULL) || (right_range == NULL)) { 3173 if ((left_range == NULL) || (right_range == NULL)) {
3040 range_ = new Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); 3174 range_ = Range::UnknownSmi();
3041 return; 3175 return;
3042 } 3176 }
3043 3177
3044 RangeBoundary left_min = 3178 Range* possible_range = Range::BinaryOp(op_kind(),
3045 IsArrayLength(left_defn) ? 3179 left_range,
3046 RangeBoundary::FromDefinition(left_defn) : left_range->min(); 3180 right_range,
3181 left_defn);
3047 3182
3048 RangeBoundary left_max = 3183 if ((range_ == NULL) && (possible_range == NULL)) {
3049 IsArrayLength(left_defn) ? 3184 // Initialize.
3050 RangeBoundary::FromDefinition(left_defn) : left_range->max(); 3185 range_ = Range::UnknownSmi();
3051 3186 return;
3052 RangeBoundary min;
3053 RangeBoundary max;
3054 switch (op_kind()) {
3055 case Token::kADD:
3056 if (!SymbolicAdd(left_min, right_range->min(), &min)) {
3057 min =
3058 RangeBoundary::Add(Range::ConstantMin(left_range),
3059 Range::ConstantMin(right_range),
3060 RangeBoundary::NegativeInfinity());
3061 }
3062
3063 if (!SymbolicAdd(left_max, right_range->max(), &max)) {
3064 max =
3065 RangeBoundary::Add(Range::ConstantMax(right_range),
3066 Range::ConstantMax(left_range),
3067 RangeBoundary::PositiveInfinity());
3068 }
3069 break;
3070
3071 case Token::kSUB:
3072 if (!SymbolicSub(left_min, right_range->max(), &min)) {
3073 min =
3074 RangeBoundary::Sub(Range::ConstantMin(left_range),
3075 Range::ConstantMax(right_range),
3076 RangeBoundary::NegativeInfinity());
3077 }
3078
3079 if (!SymbolicSub(left_max, right_range->min(), &max)) {
3080 max =
3081 RangeBoundary::Sub(Range::ConstantMax(left_range),
3082 Range::ConstantMin(right_range),
3083 RangeBoundary::PositiveInfinity());
3084 }
3085 break;
3086
3087 case Token::kMUL: {
3088 const int64_t left_max = ConstantAbsMax(left_range);
3089 const int64_t right_max = ConstantAbsMax(right_range);
3090 ASSERT(left_max <= -kSmiMin);
3091 ASSERT(right_max <= -kSmiMin);
3092 if ((left_max == 0) || (right_max <= kMaxInt64 / left_max)) {
3093 // Product of left and right max values stays in 64 bit range.
3094 const int64_t result_max = left_max * right_max;
3095 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) {
3096 const intptr_t r_min =
3097 OnlyPositiveOrZero(left_range, right_range) ? 0 : -result_max;
3098 min = RangeBoundary::FromConstant(r_min);
3099 const intptr_t r_max =
3100 OnlyNegativeOrZero(left_range, right_range) ? 0 : result_max;
3101 max = RangeBoundary::FromConstant(r_max);
3102 break;
3103 }
3104 }
3105 if (range_ == NULL) {
3106 range_ = Range::Unknown();
3107 }
3108 return;
3109 }
3110 case Token::kSHL: {
3111 Range::Shl(left_range, right_range, &min, &max);
3112 break;
3113 }
3114 case Token::kBIT_AND:
3115 if (Range::ConstantMin(right_range).value() >= 0) {
3116 min = RangeBoundary::FromConstant(0);
3117 max = Range::ConstantMax(right_range);
3118 break;
3119 }
3120 if (Range::ConstantMin(left_range).value() >= 0) {
3121 min = RangeBoundary::FromConstant(0);
3122 max = Range::ConstantMax(left_range);
3123 break;
3124 }
3125
3126 if (range_ == NULL) {
3127 range_ = Range::Unknown();
3128 }
3129 return;
3130
3131 default:
3132 if (range_ == NULL) {
3133 range_ = Range::Unknown();
3134 }
3135 return;
3136 } 3187 }
3137 3188
3138 ASSERT(!min.IsUnknown() && !max.IsUnknown()); 3189 if (possible_range == NULL) {
3139 set_overflow(min.LowerBound().Overflowed() || max.UpperBound().Overflowed()); 3190 // Nothing new.
3191 return;
3192 }
3140 3193
3141 if (min.IsConstant()) min.Clamp(); 3194 range_ = possible_range;
3142 if (max.IsConstant()) max.Clamp();
3143 3195
3144 range_ = new Range(min, max); 3196 ASSERT(!range_->min().IsUnknown() && !range_->max().IsUnknown());
3197 // Calculate overflowed status before clamping.
3198 const bool overflowed = range_->min().LowerBound().OverflowedSmi() ||
3199 range_->max().UpperBound().OverflowedSmi();
3200
3201 // Clamp value to be within smi range.
3202 range_->Clamp(RangeBoundary::kRangeBoundarySmi);
3203
3204 set_overflow(overflowed);
3145 } 3205 }
3146 3206
3147 3207
3208 void BinaryMintOpInstr::InferRange() {
3209 // TODO(vegorov): canonicalize BinaryMintOpInstr to always have constant on
3210 // the right and a non-constant on the left.
3211 Definition* left_defn = left()->definition();
3212
3213 Range* left_range = left_defn->range();
3214 Range* right_range = right()->definition()->range();
3215
3216 if ((left_range == NULL) || (right_range == NULL)) {
3217 range_ = Range::Unknown();
3218 return;
3219 }
3220
3221 Range* possible_range = Range::BinaryOp(op_kind(),
3222 left_range,
3223 right_range,
3224 left_defn);
3225
3226 if ((range_ == NULL) && (possible_range == NULL)) {
3227 // Initialize.
3228 range_ = Range::Unknown();
3229 return;
3230 }
3231
3232 if (possible_range == NULL) {
3233 // Nothing new.
3234 return;
3235 }
3236
3237 range_ = possible_range;
3238
3239 ASSERT(!range_->min().IsUnknown() && !range_->max().IsUnknown());
3240
3241 // Clamp value to be within mint range.
3242 range_->Clamp(RangeBoundary::kRangeBoundaryInt64);
Vyacheslav Egorov (Google) 2014/06/19 17:27:29 Any reason for not computing overflow state to mat
Cutch 2014/06/19 18:39:35 We currently don't track overflow / truncating on
3243 }
3244
3245
3148 bool Range::IsPositive() const { 3246 bool Range::IsPositive() const {
3149 if (min().IsNegativeInfinity()) { 3247 if (min().IsNegativeInfinity()) {
3150 return false; 3248 return false;
3151 } 3249 }
3152 if (min().LowerBound().value() < 0) { 3250 if (min().LowerBound().ConstantValue() < 0) {
3153 return false; 3251 return false;
3154 } 3252 }
3155 if (max().IsPositiveInfinity()) { 3253 if (max().IsPositiveInfinity()) {
3156 return true; 3254 return true;
3157 } 3255 }
3158 return max().UpperBound().value() >= 0; 3256 return max().UpperBound().ConstantValue() >= 0;
3159 } 3257 }
3160 3258
3161 3259
3162 bool Range::IsNegative() const { 3260 bool Range::OnlyLessThanOrEqualTo(int64_t val) const {
3163 if (max().IsPositiveInfinity()) {
3164 return false;
3165 }
3166 if (max().UpperBound().value() >= 0) {
3167 return false;
3168 }
3169 if (min().IsNegativeInfinity()) {
3170 return true;
3171 }
3172 return min().LowerBound().value() < 0;
3173 }
3174
3175
3176 bool Range::OnlyLessThanOrEqualTo(intptr_t val) const {
3177 if (max().IsPositiveInfinity()) { 3261 if (max().IsPositiveInfinity()) {
3178 // Cannot be true. 3262 // Cannot be true.
3179 return false; 3263 return false;
3180 } 3264 }
3181 if (max().UpperBound().value() > val) { 3265 if (max().UpperBound().ConstantValue() > val) {
3182 // Not true. 3266 // Not true.
3183 return false; 3267 return false;
3184 } 3268 }
3185 if (!min().IsNegativeInfinity()) { 3269 return true;
3186 if (min().LowerBound().value() > val) { 3270 }
3187 // Lower bound is > value. 3271
3188 return false; 3272
3189 } 3273 bool Range::OnlyGreaterThanOrEqualTo(int64_t val) const {
3274 if (min().IsNegativeInfinity()) {
3275 return false;
3276 }
3277 if (min().LowerBound().ConstantValue() < val) {
3278 return false;
3190 } 3279 }
3191 return true; 3280 return true;
3192 } 3281 }
3193 3282
3194 3283
3195 // Inclusive. 3284 // Inclusive.
3196 bool Range::IsWithin(intptr_t min_int, intptr_t max_int) const { 3285 bool Range::IsWithin(int64_t min_int, int64_t max_int) const {
3197 RangeBoundary lower_min = min().LowerBound(); 3286 RangeBoundary lower_min = min().LowerBound();
3198 if (lower_min.IsNegativeInfinity() || (lower_min.value() < min_int)) { 3287 if (lower_min.IsNegativeInfinity() || (lower_min.ConstantValue() < min_int)) {
3199 return false; 3288 return false;
3200 } 3289 }
3201 RangeBoundary upper_max = max().UpperBound(); 3290 RangeBoundary upper_max = max().UpperBound();
3202 if (upper_max.IsPositiveInfinity() || (upper_max.value() > max_int)) { 3291 if (upper_max.IsPositiveInfinity() || (upper_max.ConstantValue() > max_int)) {
3203 return false; 3292 return false;
3204 } 3293 }
3205 return true; 3294 return true;
3206 } 3295 }
3207 3296
3208 3297
3209 bool Range::Overlaps(intptr_t min_int, intptr_t max_int) const { 3298 bool Range::Overlaps(int64_t min_int, int64_t max_int) const {
3210 const intptr_t this_min = min().IsNegativeInfinity() ? 3299 RangeBoundary lower = min().LowerBound();
3211 kIntptrMin : min().LowerBound().value(); 3300 RangeBoundary upper = max().UpperBound();
3212 const intptr_t this_max = max().IsPositiveInfinity() ? 3301 const int64_t this_min = lower.IsNegativeInfinity() ?
3213 kIntptrMax : max().UpperBound().value(); 3302 RangeBoundary::kMin : lower.ConstantValue();
3303 const int64_t this_max = upper.IsPositiveInfinity() ?
3304 RangeBoundary::kMax : upper.ConstantValue();
3214 if ((this_min <= min_int) && (min_int <= this_max)) return true; 3305 if ((this_min <= min_int) && (min_int <= this_max)) return true;
3215 if ((this_min <= max_int) && (max_int <= this_max)) return true; 3306 if ((this_min <= max_int) && (max_int <= this_max)) return true;
3216 if ((min_int < this_min) && (max_int > this_max)) return true; 3307 if ((min_int < this_min) && (max_int > this_max)) return true;
3217 return false; 3308 return false;
3218 } 3309 }
3219 3310
3220 3311
3221 bool Range::IsUnsatisfiable() const { 3312 bool Range::IsUnsatisfiable() const {
3222 // Infinity case: [+inf, ...] || [..., -inf] 3313 // Infinity case: [+inf, ...] || [..., -inf]
3223 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) { 3314 if (min().IsPositiveInfinity() || max().IsNegativeInfinity()) {
3224 return true; 3315 return true;
3225 } 3316 }
3226 // Constant case: For example [0, -1]. 3317 // Constant case: For example [0, -1].
3227 if (Range::ConstantMin(this).value() > Range::ConstantMax(this).value()) { 3318 if (Range::ConstantMin(this).ConstantValue() >
3319 Range::ConstantMax(this).ConstantValue()) {
3228 return true; 3320 return true;
3229 } 3321 }
3230 // Symbol case: For example [v+1, v]. 3322 // Symbol case: For example [v+1, v].
3231 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) { 3323 if (DependOnSameSymbol(min(), max()) && min().offset() > max().offset()) {
3232 return true; 3324 return true;
3233 } 3325 }
3234 return false; 3326 return false;
3235 } 3327 }
3236 3328
3237 3329
3238 void Range::Shl(Range* left, 3330 void Range::Clamp(RangeBoundary::RangeSize size) {
3239 Range* right, 3331 min_ = min_.Clamp(size);
3332 max_ = max_.Clamp(size);
3333 }
3334
3335
3336 void Range::Shl(const Range* left,
3337 const Range* right,
3240 RangeBoundary* result_min, 3338 RangeBoundary* result_min,
3241 RangeBoundary* result_max) { 3339 RangeBoundary* result_max) {
3340 ASSERT(left != NULL);
3341 ASSERT(right != NULL);
3342 ASSERT(result_min != NULL);
3343 ASSERT(result_max != NULL);
3242 RangeBoundary left_max = Range::ConstantMax(left); 3344 RangeBoundary left_max = Range::ConstantMax(left);
3243 RangeBoundary left_min = Range::ConstantMin(left); 3345 RangeBoundary left_min = Range::ConstantMin(left);
3244 // A negative shift count always deoptimizes (and throws), so the minimum 3346 // A negative shift count always deoptimizes (and throws), so the minimum
3245 // shift count is zero. 3347 // shift count is zero.
3246 intptr_t right_max = Utils::Maximum(Range::ConstantMax(right).value(), 3348 int64_t right_max = Utils::Maximum(Range::ConstantMax(right).ConstantValue(),
3247 static_cast<intptr_t>(0)); 3349 static_cast<int64_t>(0));
3248 intptr_t right_min = Utils::Maximum(Range::ConstantMin(right).value(), 3350 int64_t right_min = Utils::Maximum(Range::ConstantMin(right).ConstantValue(),
3249 static_cast<intptr_t>(0)); 3351 static_cast<int64_t>(0));
3250 3352
3251 *result_min = RangeBoundary::Shl( 3353 *result_min = RangeBoundary::Shl(
3252 left_min, 3354 left_min,
3253 left_min.value() > 0 ? right_min : right_max, 3355 left_min.ConstantValue() > 0 ? right_min : right_max,
3254 left_min.value() > 0 3356 left_min.ConstantValue() > 0
3255 ? RangeBoundary::PositiveInfinity() 3357 ? RangeBoundary::PositiveInfinity()
3256 : RangeBoundary::NegativeInfinity()); 3358 : RangeBoundary::NegativeInfinity());
3257 3359
3258 *result_max = RangeBoundary::Shl( 3360 *result_max = RangeBoundary::Shl(
3259 left_max, 3361 left_max,
3260 left_max.value() > 0 ? right_max : right_min, 3362 left_max.ConstantValue() > 0 ? right_max : right_min,
3261 left_max.value() > 0 3363 left_max.ConstantValue() > 0
3262 ? RangeBoundary::PositiveInfinity() 3364 ? RangeBoundary::PositiveInfinity()
3263 : RangeBoundary::NegativeInfinity()); 3365 : RangeBoundary::NegativeInfinity());
3264 } 3366 }
3265 3367
3266 3368
3369 bool Range::And(const Range* left_range,
3370 const Range* right_range,
3371 RangeBoundary* min,
3372 RangeBoundary* max) {
3373 ASSERT(left_range != NULL);
3374 ASSERT(right_range != NULL);
3375 ASSERT(min != NULL);
3376 ASSERT(max != NULL);
3377
3378 if (Range::ConstantMin(right_range).ConstantValue() >= 0) {
3379 *min = RangeBoundary::FromConstant(0);
3380 *max = Range::ConstantMax(right_range);
3381 return true;
3382 }
3383
3384 if (Range::ConstantMin(left_range).ConstantValue() >= 0) {
3385 *min = RangeBoundary::FromConstant(0);
3386 *max = Range::ConstantMax(left_range);
3387 return true;
3388 }
3389
3390 return false;
3391 }
3392
3393
3394 void Range::Add(const Range* left_range,
3395 const Range* right_range,
3396 RangeBoundary* min,
Vyacheslav Egorov (Google) 2014/06/19 17:27:29 s/min/result_min/ and the same for max.
Cutch 2014/06/19 18:39:35 Done here and elsewhere.
3397 RangeBoundary* max,
3398 Definition* left_defn) {
3399 ASSERT(left_range != NULL);
3400 ASSERT(right_range != NULL);
3401 ASSERT(min != NULL);
3402 ASSERT(max != NULL);
3403
3404 RangeBoundary left_min =
3405 IsArrayLength(left_defn) ?
3406 RangeBoundary::FromDefinition(left_defn) : left_range->min();
3407
3408 RangeBoundary left_max =
3409 IsArrayLength(left_defn) ?
3410 RangeBoundary::FromDefinition(left_defn) : left_range->max();
3411
3412 if (!RangeBoundary::SymbolicAdd(left_min, right_range->min(), min)) {
3413 *min = RangeBoundary::Add(left_range->min().LowerBound(),
3414 right_range->min().LowerBound(),
3415 RangeBoundary::NegativeInfinity());
3416 }
3417 if (!RangeBoundary::SymbolicAdd(left_max, right_range->max(), max)) {
3418 *max = RangeBoundary::Add(right_range->max().UpperBound(),
3419 left_range->max().UpperBound(),
3420 RangeBoundary::PositiveInfinity());
3421 }
3422 }
3423
3424
3425 void Range::Sub(const Range* left_range,
3426 const Range* right_range,
3427 RangeBoundary* min,
3428 RangeBoundary* max,
3429 Definition* left_defn) {
3430 ASSERT(left_range != NULL);
3431 ASSERT(right_range != NULL);
3432 ASSERT(min != NULL);
3433 ASSERT(max != NULL);
3434
3435 RangeBoundary left_min =
3436 IsArrayLength(left_defn) ?
3437 RangeBoundary::FromDefinition(left_defn) : left_range->min();
3438
3439 RangeBoundary left_max =
3440 IsArrayLength(left_defn) ?
3441 RangeBoundary::FromDefinition(left_defn) : left_range->max();
3442
3443 if (!RangeBoundary::SymbolicSub(left_min, right_range->max(), min)) {
3444 *min = RangeBoundary::Sub(left_range->min().LowerBound(),
3445 right_range->max().UpperBound(),
3446 RangeBoundary::NegativeInfinity());
3447 }
3448 if (!RangeBoundary::SymbolicSub(left_max, right_range->min(), max)) {
3449 *max = RangeBoundary::Sub(left_range->max().UpperBound(),
3450 right_range->min().LowerBound(),
3451 RangeBoundary::PositiveInfinity());
3452 }
3453 }
3454
3455
3456 bool Range::Mul(const Range* left_range,
3457 const Range* right_range,
3458 RangeBoundary* min,
3459 RangeBoundary* max) {
3460 ASSERT(left_range != NULL);
3461 ASSERT(right_range != NULL);
3462 ASSERT(min != NULL);
3463 ASSERT(max != NULL);
3464
3465 const int64_t left_max = ConstantAbsMax(left_range);
3466 const int64_t right_max = ConstantAbsMax(right_range);
3467 if ((left_max <= -kSmiMin) && (right_max <= -kSmiMin) &&
3468 ((left_max == 0) || (right_max <= kMaxInt64 / left_max))) {
3469 // Product of left and right max values stays in 64 bit range.
3470 const int64_t result_max = left_max * right_max;
3471 if (Smi::IsValid64(result_max) && Smi::IsValid64(-result_max)) {
3472 const intptr_t r_min =
3473 OnlyPositiveOrZero(*left_range, *right_range) ? 0 : -result_max;
3474 *min = RangeBoundary::FromConstant(r_min);
3475 const intptr_t r_max =
3476 OnlyNegativeOrZero(*left_range, *right_range) ? 0 : result_max;
3477 *max = RangeBoundary::FromConstant(r_max);
3478 return true;
3479 }
3480 }
3481 return false;
3482 }
3483
3484
3485 // Both the a and b ranges are >= 0.
3486 bool Range::OnlyPositiveOrZero(const Range& a, const Range& b) {
3487 return a.OnlyGreaterThanOrEqualTo(0) && b.OnlyGreaterThanOrEqualTo(0);
3488 }
3489
3490
3491 // Both the a and b ranges are <= 0.
3492 bool Range::OnlyNegativeOrZero(const Range& a, const Range& b) {
3493 return a.OnlyLessThanOrEqualTo(0) && b.OnlyLessThanOrEqualTo(0);
3494 }
3495
3496
3497 // Return the maximum absolute value included in range.
3498 int64_t Range::ConstantAbsMax(const Range* range) {
3499 if (range == NULL) {
3500 return RangeBoundary::kMax;
3501 }
3502 const int64_t abs_min = Utils::Abs(Range::ConstantMin(range).ConstantValue());
3503 const int64_t abs_max = Utils::Abs(Range::ConstantMax(range).ConstantValue());
3504 return Utils::Maximum(abs_min, abs_max);
3505 }
3506
3507
3508 Range* Range::BinaryOp(const Token::Kind op,
3509 const Range* left_range,
3510 const Range* right_range,
3511 Definition* left_defn) {
3512 ASSERT(left_range != NULL);
3513 ASSERT(right_range != NULL);
3514
3515 // Both left and right ranges are finite.
3516 ASSERT(left_range->IsFinite());
3517 ASSERT(right_range->IsFinite());
3518
3519 RangeBoundary min;
3520 RangeBoundary max;
3521 ASSERT(min.IsUnknown() && max.IsUnknown());
3522
3523 switch (op) {
3524 case Token::kADD:
3525 Range::Add(left_range, right_range, &min, &max, left_defn);
3526 break;
3527 case Token::kSUB:
3528 Range::Sub(left_range, right_range, &min, &max, left_defn);
3529 break;
3530 case Token::kMUL: {
3531 if (!Range::Mul(left_range, right_range, &min, &max)) {
3532 return NULL;
3533 }
3534 break;
3535 }
3536 case Token::kSHL: {
3537 Range::Shl(left_range, right_range, &min, &max);
3538 break;
3539 }
3540 case Token::kBIT_AND:
3541 if (!Range::And(left_range, right_range, &min, &max)) {
3542 return NULL;
3543 }
3544 break;
3545 default:
3546 return NULL;
3547 break;
3548 }
3549
3550 ASSERT(!min.IsUnknown() && !max.IsUnknown());
3551
3552 return new Range(min, max);
3553 }
3554
3555
3267 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) { 3556 bool CheckArrayBoundInstr::IsFixedLengthArrayType(intptr_t cid) {
3268 return LoadFieldInstr::IsFixedLengthArrayCid(cid); 3557 return LoadFieldInstr::IsFixedLengthArrayCid(cid);
3269 } 3558 }
3270 3559
3271 3560
3272 bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) { 3561 bool CheckArrayBoundInstr::IsRedundant(RangeBoundary length) {
3273 Range* index_range = index()->definition()->range(); 3562 Range* index_range = index()->definition()->range();
3274 3563
3275 // Range of the index is unknown can't decide if the check is redundant. 3564 // Range of the index is unknown can't decide if the check is redundant.
3276 if (index_range == NULL) { 3565 if (index_range == NULL) {
3277 return false; 3566 return false;
3278 } 3567 }
3279 3568
3280 // Range of the index is not positive. Check can't be redundant. 3569 // Range of the index is not positive. Check can't be redundant.
3281 if (Range::ConstantMin(index_range).value() < 0) { 3570 if (Range::ConstantMinSmi(index_range).ConstantValue() < 0) {
3282 return false; 3571 return false;
3283 } 3572 }
3284 3573
3285 RangeBoundary max = CanonicalizeBoundary(index_range->max(), 3574 RangeBoundary max = CanonicalizeBoundary(index_range->max(),
3286 RangeBoundary::PositiveInfinity()); 3575 RangeBoundary::PositiveInfinity());
3287 3576
3288 if (max.Overflowed()) { 3577 if (max.OverflowedSmi()) {
3289 return false; 3578 return false;
3290 } 3579 }
3291 3580
3292 3581
3293 RangeBoundary max_upper = max.UpperBound(); 3582 RangeBoundary max_upper = max.UpperBound();
3294 RangeBoundary length_lower = length.LowerBound(); 3583 RangeBoundary length_lower = length.LowerBound();
3295 3584
3296 if (max_upper.Overflowed() || length_lower.Overflowed()) { 3585 if (max_upper.OverflowedSmi() || length_lower.OverflowedSmi()) {
3297 return false; 3586 return false;
3298 } 3587 }
3299 3588
3300 // Try to compare constant boundaries. 3589 // Try to compare constant boundaries.
3301 if (max_upper.value() < length_lower.value()) { 3590 if (max_upper.ConstantValue() < length_lower.ConstantValue()) {
3302 return true; 3591 return true;
3303 } 3592 }
3304 3593
3305 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity()); 3594 length = CanonicalizeBoundary(length, RangeBoundary::PositiveInfinity());
3306 if (length.Overflowed()) { 3595 if (length.OverflowedSmi()) {
3307 return false; 3596 return false;
3308 } 3597 }
3309 3598
3310 // Try symbolic comparison. 3599 // Try symbolic comparison.
3311 do { 3600 do {
3312 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset(); 3601 if (DependOnSameSymbol(max, length)) return max.offset() < length.offset();
3313 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length)); 3602 } while (CanonicalizeMaxBoundary(&max) || CanonicalizeMinBoundary(&length));
3314 3603
3315 // Failed to prove that maximum is bounded with array length. 3604 // Failed to prove that maximum is bounded with array length.
3316 return false; 3605 return false;
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
3589 case Token::kTRUNCDIV: return 0; 3878 case Token::kTRUNCDIV: return 0;
3590 case Token::kMOD: return 1; 3879 case Token::kMOD: return 1;
3591 default: UNIMPLEMENTED(); return -1; 3880 default: UNIMPLEMENTED(); return -1;
3592 } 3881 }
3593 } 3882 }
3594 3883
3595 3884
3596 #undef __ 3885 #undef __
3597 3886
3598 } // namespace dart 3887 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698