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/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 6827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6838 // All phis in the worklist are redundant and have the same computed | 6838 // All phis in the worklist are redundant and have the same computed |
| 6839 // value on all code paths. | 6839 // value on all code paths. |
| 6840 ASSERT(value != NULL); | 6840 ASSERT(value != NULL); |
| 6841 for (intptr_t i = 0; i < worklist_.length(); i++) { | 6841 for (intptr_t i = 0; i < worklist_.length(); i++) { |
| 6842 worklist_[i]->ReplaceUsesWith(value); | 6842 worklist_[i]->ReplaceUsesWith(value); |
| 6843 } | 6843 } |
| 6844 | 6844 |
| 6845 return true; | 6845 return true; |
| 6846 } | 6846 } |
| 6847 | 6847 |
| 6848 bool AddPhiPairToWorklist(PhiInstr* a, PhiInstr* b) { | 6848 // Returns true if definitions are congruent assuming their inputs |
| 6849 // Can't compare two phis from different blocks. | 6849 // are congruent. |
| 6850 if (a->block() != b->block()) { | 6850 bool CanBeCongruent(Definition* a, Definition* b) { |
| 6851 return (a->tag() == b->tag()) && | |
| 6852 ((a->IsPhi() && (a->GetBlock() == b->GetBlock())) || | |
| 6853 (a->AllowsCSE() && a->Dependencies().IsNone() && | |
| 6854 a->AttributesEqual(b))); | |
| 6855 } | |
| 6856 | |
| 6857 // Given two definitions check if they are congruent under assumption that | |
| 6858 // their inputs will be proven congruent. If they are - add them to the | |
| 6859 // worklist to check their inputs' congruency. | |
| 6860 // Returns true if pair was added to the worklist or is already in the | |
| 6861 // worklist and false if a and b are not congruent. | |
| 6862 bool AddPairToCongruencyWorklist(Definition* a, Definition* b) { | |
| 6863 if (!CanBeCongruent(a, b)) { | |
| 6851 return false; | 6864 return false; |
| 6852 } | 6865 } |
| 6853 | 6866 |
| 6854 // If a is already in the worklist check if it is being compared to b. | 6867 // If a is already in the worklist check if it is being compared to b. |
| 6855 // Give up if it is not. | 6868 // Give up if it is not. |
| 6856 if (in_worklist_->Contains(a->ssa_temp_index())) { | 6869 if (in_worklist_->Contains(a->ssa_temp_index())) { |
| 6857 for (intptr_t i = 0; i < worklist_.length(); i += 2) { | 6870 for (intptr_t i = 0; i < congruency_worklist_.length(); i += 2) { |
| 6858 if (a == worklist_[i]) { | 6871 if (a == congruency_worklist_[i]) { |
| 6859 return (b == worklist_[i + 1]); | 6872 return (b == congruency_worklist_[i + 1]); |
| 6860 } | 6873 } |
| 6861 } | 6874 } |
| 6862 UNREACHABLE(); | 6875 UNREACHABLE(); |
| 6876 } else if (in_worklist_->Contains(b->ssa_temp_index())) { | |
| 6877 return AddPairToCongruencyWorklist(b, a); | |
| 6863 } | 6878 } |
| 6864 | 6879 |
| 6865 worklist_.Add(a); | 6880 congruency_worklist_.Add(a); |
| 6866 worklist_.Add(b); | 6881 congruency_worklist_.Add(b); |
| 6867 in_worklist_->Add(a->ssa_temp_index()); | 6882 in_worklist_->Add(a->ssa_temp_index()); |
| 6868 return true; | 6883 return true; |
| 6869 } | 6884 } |
| 6870 | 6885 |
| 6871 // Replace the given phi with another if they are equal. | 6886 bool AreInputsCongruent(Definition* a, Definition* b) { |
| 6887 ASSERT(a->tag() == b->tag()); | |
| 6888 ASSERT(a->InputCount() == b->InputCount()); | |
| 6889 for (intptr_t j = 0; j < a->InputCount(); j++) { | |
| 6890 Definition* inputA = a->InputAt(j)->definition(); | |
| 6891 Definition* inputB = b->InputAt(j)->definition(); | |
| 6892 | |
| 6893 if (inputA != inputB) { | |
| 6894 if (!AddPairToCongruencyWorklist(inputA, inputB)) { | |
| 6895 return false; | |
| 6896 } | |
| 6897 } | |
| 6898 } | |
| 6899 return true; | |
| 6900 } | |
| 6901 | |
| 6902 // Returns true if instruction dom dominates instruction other. | |
| 6903 static bool Dominates(Instruction* dom, Instruction* other) { | |
| 6904 BlockEntryInstr* dom_block = dom->GetBlock(); | |
| 6905 BlockEntryInstr* other_block = other->GetBlock(); | |
| 6906 | |
| 6907 if (dom_block == other_block) { | |
| 6908 for (Instruction* current = dom->next(); | |
| 6909 current != NULL; | |
| 6910 current = current->next()) { | |
| 6911 if (current == other) { | |
| 6912 return true; | |
| 6913 } | |
| 6914 } | |
| 6915 return false; | |
| 6916 } | |
| 6917 | |
| 6918 return dom_block->Dominates(other_block); | |
| 6919 } | |
| 6920 | |
| 6921 // Replace the given phi with another if they are congruent. | |
| 6872 // Returns true if succeeds. | 6922 // Returns true if succeeds. |
| 6873 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) { | 6923 bool ReplacePhiWith(PhiInstr* phi, PhiInstr* replacement) { |
| 6874 ASSERT(phi->InputCount() == replacement->InputCount()); | 6924 ASSERT(phi->InputCount() == replacement->InputCount()); |
| 6875 ASSERT(phi->block() == replacement->block()); | 6925 ASSERT(phi->block() == replacement->block()); |
| 6876 | 6926 |
| 6877 worklist_.Clear(); | 6927 congruency_worklist_.Clear(); |
| 6878 if (in_worklist_ == NULL) { | 6928 if (in_worklist_ == NULL) { |
| 6879 in_worklist_ = new(I) BitVector(graph_->current_ssa_temp_index()); | 6929 in_worklist_ = new(I) BitVector(graph_->current_ssa_temp_index()); |
| 6880 } else { | 6930 } else { |
| 6881 in_worklist_->Clear(); | 6931 in_worklist_->Clear(); |
| 6882 } | 6932 } |
| 6883 | 6933 |
| 6884 // During the comparison worklist contains pairs of phis to be compared. | 6934 // During the comparison worklist contains pairs of definintions to be |
|
Florian Schneider
2014/09/04 12:30:48
s/definintions/definitions/
Vyacheslav Egorov (Google)
2014/09/04 12:56:13
Done.
| |
| 6885 AddPhiPairToWorklist(phi, replacement); | 6935 // compared. |
| 6936 if (!AddPairToCongruencyWorklist(phi, replacement)) { | |
| 6937 return false; | |
| 6938 } | |
| 6886 | 6939 |
| 6887 // Process the worklist. It might grow during each comparison step. | 6940 // Process the worklist. It might grow during each comparison step. |
| 6888 for (intptr_t i = 0; i < worklist_.length(); i += 2) { | 6941 for (intptr_t i = 0; i < congruency_worklist_.length(); i += 2) { |
| 6889 PhiInstr* a = worklist_[i]; | 6942 if (!AreInputsCongruent(congruency_worklist_[i], |
| 6890 PhiInstr* b = worklist_[i + 1]; | 6943 congruency_worklist_[i + 1])) { |
| 6891 | 6944 return false; |
| 6892 // Compare phi inputs. | |
| 6893 for (intptr_t j = 0; j < a->InputCount(); j++) { | |
| 6894 Definition* inputA = a->InputAt(j)->definition(); | |
| 6895 Definition* inputB = b->InputAt(j)->definition(); | |
| 6896 | |
| 6897 if (inputA != inputB) { | |
| 6898 // If inputs are unequal by they are phis then add them to | |
| 6899 // the worklist for recursive comparison. | |
| 6900 if (inputA->IsPhi() && inputB->IsPhi() && | |
| 6901 AddPhiPairToWorklist(inputA->AsPhi(), inputB->AsPhi())) { | |
| 6902 continue; | |
| 6903 } | |
| 6904 return false; // Not equal. | |
| 6905 } | |
| 6906 } | 6945 } |
| 6907 } | 6946 } |
| 6908 | 6947 |
| 6909 // At this point worklist contains pairs of equal phis. Replace the first | 6948 // At this point worklist contains pairs of congruent definitions. |
| 6910 // phi in the pair with the second. | 6949 // Replace the one membmer of the pair with another maintaining proper |
| 6911 for (intptr_t i = 0; i < worklist_.length(); i += 2) { | 6950 // domination relation between definitions and uses. |
| 6912 PhiInstr* a = worklist_[i]; | 6951 for (intptr_t i = 0; i < congruency_worklist_.length(); i += 2) { |
| 6913 PhiInstr* b = worklist_[i + 1]; | 6952 Definition* a = congruency_worklist_[i]; |
| 6953 Definition* b = congruency_worklist_[i + 1]; | |
| 6954 | |
| 6955 // If these definitions are not phis then we need to pick up one | |
| 6956 // that dominates another as the replacement: if a dominates b swap them. | |
| 6957 // Note: both a and b are used as a phi input at the same block B which | |
| 6958 // means a dominates B and b dominates B, which guarantees that either | |
| 6959 // a dominates b or b dominates a. | |
| 6960 if (!a->IsPhi()) { | |
| 6961 if (Dominates(a, b)) { | |
| 6962 Definition* t = a; | |
| 6963 a = b; | |
| 6964 b = t; | |
| 6965 } | |
| 6966 ASSERT(Dominates(b, a)); | |
| 6967 } | |
| 6968 | |
| 6969 if (FLAG_trace_load_optimization) { | |
| 6970 OS::Print("Replacing %s with congruent %s\n", | |
| 6971 a->ToCString(), | |
| 6972 b->ToCString()); | |
| 6973 } | |
| 6974 | |
| 6914 a->ReplaceUsesWith(b); | 6975 a->ReplaceUsesWith(b); |
| 6915 if (a->is_alive()) { | 6976 if (a->IsPhi()) { |
| 6916 a->mark_dead(); | 6977 // We might be replacing a phi introduced by the load forwarding |
| 6917 a->block()->RemovePhi(a); | 6978 // that is not inserted in the graph yet. |
| 6918 a->UnuseAllInputs(); | 6979 ASSERT(b->IsPhi()); |
| 6980 PhiInstr* phi_a = a->AsPhi(); | |
| 6981 if (phi_a->is_alive()) { | |
| 6982 phi_a->mark_dead(); | |
| 6983 phi_a->block()->RemovePhi(phi_a); | |
| 6984 phi_a->UnuseAllInputs(); | |
| 6985 } | |
| 6986 } else { | |
| 6987 a->RemoveFromGraph(); | |
| 6919 } | 6988 } |
| 6920 } | 6989 } |
| 6990 | |
| 6921 return true; | 6991 return true; |
| 6922 } | 6992 } |
| 6923 | 6993 |
| 6924 // Insert the given phi into the graph. Attempt to find an equal one in the | 6994 // Insert the given phi into the graph. Attempt to find an equal one in the |
| 6925 // target block first. | 6995 // target block first. |
| 6926 // Returns true if the phi was inserted and false if it was replaced. | 6996 // Returns true if the phi was inserted and false if it was replaced. |
| 6927 bool EmitPhi(PhiInstr* phi) { | 6997 bool EmitPhi(PhiInstr* phi) { |
| 6928 for (PhiIterator it(phi->block()); !it.Done(); it.Advance()) { | 6998 for (PhiIterator it(phi->block()); !it.Done(); it.Advance()) { |
| 6929 if (ReplacePhiWith(phi, it.Current())) { | 6999 if (ReplacePhiWith(phi, it.Current())) { |
| 6930 return false; | 7000 return false; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6989 // represent those ids. | 7059 // represent those ids. |
| 6990 GrowableArray<ZoneGrowableArray<Definition*>*> out_values_; | 7060 GrowableArray<ZoneGrowableArray<Definition*>*> out_values_; |
| 6991 | 7061 |
| 6992 // List of phis generated during ComputeOutValues and ForwardLoads. | 7062 // List of phis generated during ComputeOutValues and ForwardLoads. |
| 6993 // Some of these phis might be redundant and thus a separate pass is | 7063 // Some of these phis might be redundant and thus a separate pass is |
| 6994 // needed to emit only non-redundant ones. | 7064 // needed to emit only non-redundant ones. |
| 6995 GrowableArray<PhiInstr*> phis_; | 7065 GrowableArray<PhiInstr*> phis_; |
| 6996 | 7066 |
| 6997 // Auxiliary worklist used by redundant phi elimination. | 7067 // Auxiliary worklist used by redundant phi elimination. |
| 6998 GrowableArray<PhiInstr*> worklist_; | 7068 GrowableArray<PhiInstr*> worklist_; |
| 7069 GrowableArray<Definition*> congruency_worklist_; | |
| 6999 BitVector* in_worklist_; | 7070 BitVector* in_worklist_; |
| 7000 | 7071 |
| 7072 | |
|
Florian Schneider
2014/09/04 12:30:48
2dd
Vyacheslav Egorov (Google)
2014/09/04 12:56:13
Done.
| |
| 7073 | |
| 7001 // True if any load was eliminated. | 7074 // True if any load was eliminated. |
| 7002 bool forwarded_; | 7075 bool forwarded_; |
| 7003 | 7076 |
| 7004 DISALLOW_COPY_AND_ASSIGN(LoadOptimizer); | 7077 DISALLOW_COPY_AND_ASSIGN(LoadOptimizer); |
| 7005 }; | 7078 }; |
| 7006 | 7079 |
| 7007 | 7080 |
| 7008 class StoreOptimizer : public LivenessAnalysis { | 7081 class StoreOptimizer : public LivenessAnalysis { |
| 7009 public: | 7082 public: |
| 7010 StoreOptimizer(FlowGraph* graph, | 7083 StoreOptimizer(FlowGraph* graph, |
| (...skipping 2956 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9967 | 10040 |
| 9968 // Insert materializations at environment uses. | 10041 // Insert materializations at environment uses. |
| 9969 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 10042 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
| 9970 CreateMaterializationAt( | 10043 CreateMaterializationAt( |
| 9971 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 10044 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); |
| 9972 } | 10045 } |
| 9973 } | 10046 } |
| 9974 | 10047 |
| 9975 | 10048 |
| 9976 } // namespace dart | 10049 } // namespace dart |
| OLD | NEW |