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

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

Issue 59613005: Merge (x & y) == 0 pattern to emit a single test instruction. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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/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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698