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 bpattern (a & b) == 0 where left is a bitwise and operation | |
srdjan
2013/11/05 18:30:34
s/bpattern/pattern/
Florian Schneider
2013/11/06 12:13:42
Done.
| |
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 |