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

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

Issue 537963002: Improve LoadOptimizer::ReplacePhiWith. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698