| OLD | NEW |
| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_allocator.h" | 10 #include "vm/flow_graph_allocator.h" |
| (...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 set_previous(NULL); | 753 set_previous(NULL); |
| 754 set_next(NULL); | 754 set_next(NULL); |
| 755 } | 755 } |
| 756 | 756 |
| 757 | 757 |
| 758 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) | 758 BranchInstr::BranchInstr(ComparisonInstr* comparison, bool is_checked) |
| 759 : comparison_(comparison), | 759 : comparison_(comparison), |
| 760 is_checked_(is_checked), | 760 is_checked_(is_checked), |
| 761 constrained_type_(NULL), | 761 constrained_type_(NULL), |
| 762 constant_target_(NULL) { | 762 constant_target_(NULL) { |
| 763 ASSERT(comparison->env() == NULL); |
| 763 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { | 764 for (intptr_t i = comparison->InputCount() - 1; i >= 0; --i) { |
| 764 comparison->InputAt(i)->set_instruction(this); | 765 comparison->InputAt(i)->set_instruction(this); |
| 765 } | 766 } |
| 766 } | 767 } |
| 767 | 768 |
| 768 | 769 |
| 769 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { | 770 void BranchInstr::RawSetInputAt(intptr_t i, Value* value) { |
| 770 comparison()->RawSetInputAt(i, value); | 771 comparison()->RawSetInputAt(i, value); |
| 771 } | 772 } |
| 772 | 773 |
| 773 | 774 |
| 774 // A misleadingly named function for use in template functions that replace | 775 // A misleadingly named function for use in template functions that replace |
| 775 // both definitions with definitions and branch comparisons with | 776 // both definitions with definitions and branch comparisons with |
| 776 // comparisons. In the branch case, leave the branch intact and replace its | 777 // comparisons. In the branch case, leave the branch intact and replace its |
| 777 // comparison with a new comparison not currently in the graph. | 778 // comparison with a new comparison not currently in the graph. |
| 778 void BranchInstr::ReplaceWith(ComparisonInstr* other, | 779 void BranchInstr::ReplaceWith(ComparisonInstr* other, |
| 779 ForwardInstructionIterator* ignored) { | 780 ForwardInstructionIterator* ignored) { |
| 780 SetComparison(other); | 781 SetComparison(other); |
| 781 } | 782 } |
| 782 | 783 |
| 783 | 784 |
| 784 void BranchInstr::SetComparison(ComparisonInstr* comp) { | 785 void BranchInstr::SetComparison(ComparisonInstr* new_comparison) { |
| 785 for (intptr_t i = comp->InputCount() - 1; i >= 0; --i) { | 786 for (intptr_t i = new_comparison->InputCount() - 1; i >= 0; --i) { |
| 786 Value* input = comp->InputAt(i); | 787 Value* input = new_comparison->InputAt(i); |
| 787 input->definition()->AddInputUse(input); | 788 input->definition()->AddInputUse(input); |
| 788 input->set_instruction(this); | 789 input->set_instruction(this); |
| 789 } | 790 } |
| 790 // There should be no need to copy or unuse an environment. | 791 // There should be no need to copy or unuse an environment. |
| 791 ASSERT(comparison()->env() == NULL); | 792 ASSERT(comparison()->env() == NULL); |
| 793 ASSERT(new_comparison->env() == NULL); |
| 792 // Remove the current comparison's input uses. | 794 // Remove the current comparison's input uses. |
| 793 comparison()->UnuseAllInputs(); | 795 comparison()->UnuseAllInputs(); |
| 794 ASSERT(!comp->HasUses()); | 796 ASSERT(!new_comparison->HasUses()); |
| 795 comparison_ = comp; | 797 comparison_ = new_comparison; |
| 796 } | 798 } |
| 797 | 799 |
| 798 | 800 |
| 799 // ==== Postorder graph traversal. | 801 // ==== Postorder graph traversal. |
| 800 static bool IsMarked(BlockEntryInstr* block, | 802 static bool IsMarked(BlockEntryInstr* block, |
| 801 GrowableArray<BlockEntryInstr*>* preorder) { | 803 GrowableArray<BlockEntryInstr*>* preorder) { |
| 802 // Detect that a block has been visited as part of the current | 804 // Detect that a block has been visited as part of the current |
| 803 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block | 805 // DiscoverBlocks (we can call DiscoverBlocks multiple times). The block |
| 804 // will be 'marked' by (1) having a preorder number in the range of the | 806 // will be 'marked' by (1) having a preorder number in the range of the |
| 805 // preorder array and (2) being in the preorder array at that index. | 807 // preorder array and (2) being in the preorder array at that index. |
| (...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1610 other_defn->IsComparison() && | 1612 other_defn->IsComparison() && |
| 1611 (other->Type()->ToCid() == kBoolCid) && | 1613 (other->Type()->ToCid() == kBoolCid) && |
| 1612 other_defn->HasOnlyUse(other)) { | 1614 other_defn->HasOnlyUse(other)) { |
| 1613 *negated = true; | 1615 *negated = true; |
| 1614 return other_defn; | 1616 return other_defn; |
| 1615 } | 1617 } |
| 1616 return compare; | 1618 return compare; |
| 1617 } | 1619 } |
| 1618 | 1620 |
| 1619 | 1621 |
| 1622 // Recognize the pattern (a & b) == 0 where left is a bitwise and operation |
| 1623 // and right is a constant 0. |
| 1624 static bool RecognizeTestPattern(Value* left, Value* right) { |
| 1625 if (!right->BindsToConstant()) { |
| 1626 return false; |
| 1627 } |
| 1628 |
| 1629 const Object& value = right->BoundConstant(); |
| 1630 if (!value.IsSmi() || (Smi::Cast(value).Value() != 0)) { |
| 1631 return false; |
| 1632 } |
| 1633 |
| 1634 Definition* left_defn = left->definition(); |
| 1635 return left_defn->IsBinarySmiOp() && |
| 1636 (left_defn->AsBinarySmiOp()->op_kind() == Token::kBIT_AND) && |
| 1637 left_defn->HasOnlyUse(left); |
| 1638 } |
| 1639 |
| 1640 |
| 1620 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { | 1641 Instruction* BranchInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1621 // Only handle strict-compares. | 1642 // Only handle strict-compares. |
| 1622 if (comparison()->IsStrictCompare()) { | 1643 if (comparison()->IsStrictCompare()) { |
| 1623 bool negated = false; | 1644 bool negated = false; |
| 1624 Definition* replacement = | 1645 Definition* replacement = |
| 1625 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated); | 1646 CanonicalizeStrictCompare(comparison()->AsStrictCompare(), &negated); |
| 1626 if (replacement == comparison()) { | 1647 if (replacement == comparison()) { |
| 1627 return this; | 1648 return this; |
| 1628 } | 1649 } |
| 1629 ComparisonInstr* comp = replacement->AsComparison(); | 1650 ComparisonInstr* comp = replacement->AsComparison(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1657 SetComparison(comp); | 1678 SetComparison(comp); |
| 1658 if (FLAG_trace_optimization) { | 1679 if (FLAG_trace_optimization) { |
| 1659 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index()); | 1680 OS::Print("Merging comparison v%" Pd "\n", comp->ssa_temp_index()); |
| 1660 } | 1681 } |
| 1661 // Clear the comparison's temp index and ssa temp index since the | 1682 // Clear the comparison's temp index and ssa temp index since the |
| 1662 // value of the comparison is not used outside the branch anymore. | 1683 // value of the comparison is not used outside the branch anymore. |
| 1663 ASSERT(comp->input_use_list() == NULL); | 1684 ASSERT(comp->input_use_list() == NULL); |
| 1664 comp->ClearSSATempIndex(); | 1685 comp->ClearSSATempIndex(); |
| 1665 comp->ClearTempIndex(); | 1686 comp->ClearTempIndex(); |
| 1666 } | 1687 } |
| 1688 } else if (comparison()->IsEqualityCompare() && |
| 1689 comparison()->operation_cid() == kSmiCid) { |
| 1690 BinarySmiOpInstr* bit_and = NULL; |
| 1691 if (RecognizeTestPattern(comparison()->left(), comparison()->right())) { |
| 1692 bit_and = comparison()->left()->definition()->AsBinarySmiOp(); |
| 1693 } else if (RecognizeTestPattern(comparison()->right(), |
| 1694 comparison()->left())) { |
| 1695 bit_and = comparison()->right()->definition()->AsBinarySmiOp(); |
| 1696 } |
| 1697 if (bit_and != NULL) { |
| 1698 if (FLAG_trace_optimization) { |
| 1699 OS::Print("Merging test smi v%" Pd "\n", bit_and->ssa_temp_index()); |
| 1700 } |
| 1701 TestSmiInstr* test = new TestSmiInstr(comparison()->token_pos(), |
| 1702 comparison()->kind(), |
| 1703 bit_and->left()->Copy(), |
| 1704 bit_and->right()->Copy()); |
| 1705 ASSERT(!CanDeoptimize()); |
| 1706 RemoveEnvironment(); |
| 1707 flow_graph->CopyDeoptTarget(this, bit_and); |
| 1708 SetComparison(test); |
| 1709 bit_and->RemoveFromGraph(); |
| 1710 } |
| 1667 } | 1711 } |
| 1668 return this; | 1712 return this; |
| 1669 } | 1713 } |
| 1670 | 1714 |
| 1671 | 1715 |
| 1672 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { | 1716 Definition* StrictCompareInstr::Canonicalize(FlowGraph* flow_graph) { |
| 1673 bool negated = false; | 1717 bool negated = false; |
| 1674 Definition* replacement = CanonicalizeStrictCompare(this, &negated); | 1718 Definition* replacement = CanonicalizeStrictCompare(this, &negated); |
| 1675 if (negated && replacement->IsComparison()) { | 1719 if (negated && replacement->IsComparison()) { |
| 1676 ASSERT(replacement != this); | 1720 ASSERT(replacement != this); |
| (...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2877 return kCosRuntimeEntry; | 2921 return kCosRuntimeEntry; |
| 2878 default: | 2922 default: |
| 2879 UNREACHABLE(); | 2923 UNREACHABLE(); |
| 2880 } | 2924 } |
| 2881 return kSinRuntimeEntry; | 2925 return kSinRuntimeEntry; |
| 2882 } | 2926 } |
| 2883 | 2927 |
| 2884 #undef __ | 2928 #undef __ |
| 2885 | 2929 |
| 2886 } // namespace dart | 2930 } // namespace dart |
| OLD | NEW |