Chromium Code Reviews| 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/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/dart_entry.h" | 8 #include "vm/dart_entry.h" |
| 9 #include "vm/flow_graph_allocator.h" | 9 #include "vm/flow_graph_allocator.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 return result->AsBlockEntry(); | 370 return result->AsBlockEntry(); |
| 371 } | 371 } |
| 372 | 372 |
| 373 | 373 |
| 374 void ForwardInstructionIterator::RemoveCurrentFromGraph() { | 374 void ForwardInstructionIterator::RemoveCurrentFromGraph() { |
| 375 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. | 375 current_ = current_->RemoveFromGraph(true); // Set current_ to previous. |
| 376 } | 376 } |
| 377 | 377 |
| 378 | 378 |
| 379 void ForwardInstructionIterator::ReplaceCurrentWith(Definition* other) { | 379 void ForwardInstructionIterator::ReplaceCurrentWith(Definition* other) { |
| 380 Definition* defn = current_->AsDefinition(); | |
|
Vyacheslav Egorov (Google)
2013/02/08 16:44:49
This must come back before you will land it.
Kevin Millikin (Google)
2013/02/19 10:49:30
Thanks, it was an inadvertent deletion.
| |
| 381 ASSERT(defn != NULL); | |
| 382 defn->ReplaceUsesWith(other); | |
| 383 ASSERT(other->env() == NULL); | |
| 384 other->set_env(defn->env()); | |
| 385 defn->set_env(NULL); | |
| 386 ASSERT(!other->HasSSATemp()); | |
| 387 if (defn->HasSSATemp()) other->set_ssa_temp_index(defn->ssa_temp_index()); | |
| 388 | |
| 389 other->InsertBefore(current_); // So other will be current. | |
| 390 RemoveCurrentFromGraph(); | |
| 391 } | 380 } |
| 392 | 381 |
| 393 | 382 |
| 394 // Default implementation of visiting basic blocks. Can be overridden. | 383 // Default implementation of visiting basic blocks. Can be overridden. |
| 395 void FlowGraphVisitor::VisitBlocks() { | 384 void FlowGraphVisitor::VisitBlocks() { |
| 396 ASSERT(current_iterator_ == NULL); | 385 ASSERT(current_iterator_ == NULL); |
| 397 for (intptr_t i = 0; i < block_order_.length(); ++i) { | 386 for (intptr_t i = 0; i < block_order_.length(); ++i) { |
| 398 BlockEntryInstr* entry = block_order_[i]; | 387 BlockEntryInstr* entry = block_order_[i]; |
| 399 entry->Accept(this); | 388 entry->Accept(this); |
| 400 ForwardInstructionIterator it(entry); | 389 ForwardInstructionIterator it(entry); |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 InputAt(i)->RemoveFromUseList(); | 690 InputAt(i)->RemoveFromUseList(); |
| 702 } | 691 } |
| 703 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { | 692 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { |
| 704 it.CurrentValue()->RemoveFromUseList(); | 693 it.CurrentValue()->RemoveFromUseList(); |
| 705 } | 694 } |
| 706 } | 695 } |
| 707 | 696 |
| 708 | 697 |
| 709 void Definition::ReplaceWith(Definition* other, | 698 void Definition::ReplaceWith(Definition* other, |
| 710 ForwardInstructionIterator* iterator) { | 699 ForwardInstructionIterator* iterator) { |
| 700 // Record other's input uses. | |
| 701 for (intptr_t i = other->InputCount() - 1; i >= 0; --i) { | |
| 702 Value* input = other->InputAt(i); | |
| 703 input->definition()->AddInputUse(input); | |
| 704 input->set_instruction(other); | |
| 705 input->set_use_index(i); | |
| 706 } | |
| 707 // Take other's environment from this definition. | |
| 708 ASSERT(other->env() == NULL); | |
| 709 intptr_t use_index = 0; | |
| 710 for (Environment::DeepIterator it(env()); !it.Done(); it.Advance()) { | |
| 711 Value* use = it.CurrentValue(); | |
| 712 use->set_instruction(other); | |
| 713 use->set_use_index(use_index++); | |
| 714 } | |
| 715 other->set_env(env()); | |
| 716 set_env(NULL); | |
| 717 // Replace all uses of this definition with other. | |
| 718 ReplaceUsesWith(other); | |
| 719 // Reuse this instruction's SSA name for other. | |
| 720 ASSERT(!other->HasSSATemp()); | |
| 721 if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index()); | |
| 722 // Remove this definition's input uses. | |
| 723 UnuseAllInputs(); | |
| 724 | |
| 725 // Finally remove this definition from the graph. | |
| 726 previous()->LinkTo(other); | |
| 711 if ((iterator != NULL) && (this == iterator->Current())) { | 727 if ((iterator != NULL) && (this == iterator->Current())) { |
| 712 iterator->ReplaceCurrentWith(other); | 728 // Remove through the iterator. |
| 729 other->LinkTo(this); | |
| 730 iterator->RemoveCurrentFromGraph(); | |
| 713 } else { | 731 } else { |
| 714 ReplaceUsesWith(other); | |
| 715 ASSERT(other->env() == NULL); | |
| 716 other->set_env(env()); | |
| 717 set_env(NULL); | |
| 718 ASSERT(!other->HasSSATemp()); | |
| 719 if (HasSSATemp()) other->set_ssa_temp_index(ssa_temp_index()); | |
| 720 | |
| 721 previous()->LinkTo(other); | |
| 722 other->LinkTo(next()); | 732 other->LinkTo(next()); |
| 723 | |
| 724 set_previous(NULL); | |
| 725 set_next(NULL); | |
| 726 } | 733 } |
| 734 set_previous(NULL); | |
| 735 set_next(NULL); | |
| 727 } | 736 } |
| 728 | 737 |
| 729 | 738 |
| 730 bool Definition::SetPropagatedCid(intptr_t cid) { | 739 bool Definition::SetPropagatedCid(intptr_t cid) { |
| 731 if (cid == kIllegalCid) { | 740 if (cid == kIllegalCid) { |
| 732 return false; | 741 return false; |
| 733 } | 742 } |
| 734 if (propagated_cid_ == kIllegalCid) { | 743 if (propagated_cid_ == kIllegalCid) { |
| 735 // First setting, nothing has changed. | 744 // First setting, nothing has changed. |
| 736 propagated_cid_ = cid; | 745 propagated_cid_ = cid; |
| (...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1746 Definition* LoadFieldInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1755 Definition* LoadFieldInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1747 if (!IsImmutableLengthLoad()) return this; | 1756 if (!IsImmutableLengthLoad()) return this; |
| 1748 | 1757 |
| 1749 // For fixed length arrays if the array is the result of a known constructor | 1758 // For fixed length arrays if the array is the result of a known constructor |
| 1750 // call we can replace the length load with the length argument passed to | 1759 // call we can replace the length load with the length argument passed to |
| 1751 // the constructor. | 1760 // the constructor. |
| 1752 StaticCallInstr* call = value()->definition()->AsStaticCall(); | 1761 StaticCallInstr* call = value()->definition()->AsStaticCall(); |
| 1753 if (call != NULL && | 1762 if (call != NULL && |
| 1754 call->is_known_constructor() && | 1763 call->is_known_constructor() && |
| 1755 call->ResultCid() == kArrayCid) { | 1764 call->ResultCid() == kArrayCid) { |
| 1756 return call->ArgumentAt(1)->value()->definition(); | 1765 return call->ArgumentAt(1); |
| 1757 } | 1766 } |
| 1758 return this; | 1767 return this; |
| 1759 } | 1768 } |
| 1760 | 1769 |
| 1761 | 1770 |
| 1762 Definition* AssertBooleanInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1771 Definition* AssertBooleanInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1763 const intptr_t value_cid = value()->ResultCid(); | 1772 const intptr_t value_cid = value()->ResultCid(); |
| 1764 return (value_cid == kBoolCid) ? value()->definition() : this; | 1773 return (value_cid == kBoolCid) ? value()->definition() : this; |
| 1765 } | 1774 } |
| 1766 | 1775 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1821 Definition* replacement = comparison()->Canonicalize(optimizer); | 1830 Definition* replacement = comparison()->Canonicalize(optimizer); |
| 1822 if (replacement == comparison() || replacement == NULL) return this; | 1831 if (replacement == comparison() || replacement == NULL) return this; |
| 1823 ComparisonInstr* comp = replacement->AsComparison(); | 1832 ComparisonInstr* comp = replacement->AsComparison(); |
| 1824 if (comp == NULL) return this; | 1833 if (comp == NULL) return this; |
| 1825 | 1834 |
| 1826 // Replace the comparison if the replacement is used at this branch, | 1835 // Replace the comparison if the replacement is used at this branch, |
| 1827 // and has exactly one use. | 1836 // and has exactly one use. |
| 1828 if ((comp->input_use_list()->instruction() == this) && | 1837 if ((comp->input_use_list()->instruction() == this) && |
| 1829 (comp->input_use_list()->next_use() == NULL) && | 1838 (comp->input_use_list()->next_use() == NULL) && |
| 1830 (comp->env_use_list() == NULL)) { | 1839 (comp->env_use_list() == NULL)) { |
| 1840 comparison()->UnuseAllInputs(); | |
| 1831 comp->RemoveFromGraph(); | 1841 comp->RemoveFromGraph(); |
| 1832 // It is safe to pass a NULL iterator because we're replacing the | 1842 // It is safe to pass a NULL iterator because we're replacing the |
| 1833 // comparison wrapped in a BranchInstr which does not modify the | 1843 // comparison wrapped in a BranchInstr which does not modify the |
| 1834 // linked list of instructions. | 1844 // linked list of instructions. |
| 1835 ReplaceWith(comp, NULL /* ignored */); | 1845 ReplaceWith(comp, NULL /* ignored */); |
| 1836 for (intptr_t i = 0; i < comp->InputCount(); ++i) { | 1846 for (intptr_t i = 0; i < comp->InputCount(); ++i) { |
| 1837 Value* operand = comp->InputAt(i); | 1847 Value* operand = comp->InputAt(i); |
| 1838 operand->set_instruction(this); | 1848 operand->set_instruction(this); |
| 1839 } | 1849 } |
| 1840 if (FLAG_trace_optimization) { | 1850 if (FLAG_trace_optimization) { |
| 1841 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); | 1851 OS::Print("Merging comparison v%"Pd"\n", comp->ssa_temp_index()); |
| 1842 } | 1852 } |
| 1843 // Clear the comparison's use list, temp index and ssa temp index since | 1853 // Clear the comparison's temp index and ssa temp index since the |
| 1844 // the value of the comparison is not used outside the branch anymore. | 1854 // value of the comparison is not used outside the branch anymore. |
| 1845 comp->set_input_use_list(NULL); | 1855 ASSERT(comp->input_use_list() == NULL); |
| 1846 comp->ClearSSATempIndex(); | 1856 comp->ClearSSATempIndex(); |
| 1847 comp->ClearTempIndex(); | 1857 comp->ClearTempIndex(); |
| 1848 } | 1858 } |
| 1849 } | 1859 } |
| 1850 return this; | 1860 return this; |
| 1851 } | 1861 } |
| 1852 | 1862 |
| 1853 | 1863 |
| 1854 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { | 1864 Definition* StrictCompareInstr::Canonicalize(FlowGraphOptimizer* optimizer) { |
| 1855 if (!right()->BindsToConstant()) return this; | 1865 if (!right()->BindsToConstant()) return this; |
| (...skipping 1012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2868 default: | 2878 default: |
| 2869 UNREACHABLE(); | 2879 UNREACHABLE(); |
| 2870 } | 2880 } |
| 2871 return kPowRuntimeEntry; | 2881 return kPowRuntimeEntry; |
| 2872 } | 2882 } |
| 2873 | 2883 |
| 2874 | 2884 |
| 2875 #undef __ | 2885 #undef __ |
| 2876 | 2886 |
| 2877 } // namespace dart | 2887 } // namespace dart |
| OLD | NEW |