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

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

Issue 12340108: Remove dead phis as soon as they are discovered. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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.h" 5 #include "vm/flow_graph.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/flow_graph_builder.h" 8 #include "vm/flow_graph_builder.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 ASSERT(use->definition() != NULL); 138 ASSERT(use->definition() != NULL);
139 ASSERT((use->definition() != instr) || use->definition()->IsPhi()); 139 ASSERT((use->definition() != instr) || use->definition()->IsPhi());
140 ASSERT(use->instruction() == instr); 140 ASSERT(use->instruction() == instr);
141 ASSERT(use->use_index() == use_index++); 141 ASSERT(use->use_index() == use_index++);
142 ASSERT(!FLAG_verify_compiler || 142 ASSERT(!FLAG_verify_compiler ||
143 (1 == MembershipCount(use, use->definition()->env_use_list()))); 143 (1 == MembershipCount(use, use->definition()->env_use_list())));
144 } 144 }
145 } 145 }
146 Definition* defn = instr->AsDefinition(); 146 Definition* defn = instr->AsDefinition();
147 if (defn != NULL) { 147 if (defn != NULL) {
148 // Used definitions must have an SSA name. We use the name to index
149 // into bit vectors during analyses. Some definitions without SSA names
150 // (e.g., PushArgument) have environment uses.
151 ASSERT((defn->input_use_list() == NULL) || defn->HasSSATemp());
148 Value* prev = NULL; 152 Value* prev = NULL;
149 Value* curr = defn->input_use_list(); 153 Value* curr = defn->input_use_list();
150 while (curr != NULL) { 154 while (curr != NULL) {
151 ASSERT(prev == curr->previous_use()); 155 ASSERT(prev == curr->previous_use());
152 ASSERT(defn == curr->definition()); 156 ASSERT(defn == curr->definition());
153 Instruction* instr = curr->instruction(); 157 Instruction* instr = curr->instruction();
154 // The instruction should not be removed from the graph. Removed 158 // The instruction should not be removed from the graph.
155 // instructions have a NULL previous link. Phis are not removed until 159 ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) ||
156 // register allocation. Comparisons used only in a branch will have a
157 // NULL previous link though they are still in the graph.
158 ASSERT(instr->IsPhi() ||
159 (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) ||
160 (instr->previous() != NULL)); 160 (instr->previous() != NULL));
161 ASSERT(curr == instr->InputAt(curr->use_index())); 161 ASSERT(curr == instr->InputAt(curr->use_index()));
162 prev = curr; 162 prev = curr;
163 curr = curr->next_use(); 163 curr = curr->next_use();
164 } 164 }
165 165
166 prev = NULL; 166 prev = NULL;
167 curr = defn->env_use_list(); 167 curr = defn->env_use_list();
168 while (curr != NULL) { 168 while (curr != NULL) {
169 ASSERT(prev == curr->previous_use()); 169 ASSERT(prev == curr->previous_use());
170 ASSERT(defn == curr->definition()); 170 ASSERT(defn == curr->definition());
171 Instruction* instr = curr->instruction(); 171 Instruction* instr = curr->instruction();
172 ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index())); 172 ASSERT(curr == instr->env()->ValueAtUseIndex(curr->use_index()));
173 ASSERT(instr->IsPhi() || 173 ASSERT((instr->IsPhi() && instr->AsPhi()->is_alive()) ||
174 (instr->IsDefinition() && instr->AsDefinition()->IsComparison()) ||
175 (instr->previous() != NULL)); 174 (instr->previous() != NULL));
176 prev = curr; 175 prev = curr;
177 curr = curr->next_use(); 176 curr = curr->next_use();
178 } 177 }
179 } 178 }
180 } 179 }
181 180
182 181
183 bool FlowGraph::VerifyUseLists() { 182 bool FlowGraph::VerifyUseLists() {
184 // Verify the initial definitions. 183 // Verify the initial definitions.
185 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { 184 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) {
186 VerifyUseListsInInstruction((*graph_entry_->initial_definitions())[i]); 185 VerifyUseListsInInstruction((*graph_entry_->initial_definitions())[i]);
187 } 186 }
188 187
189 // Verify phis in join entries and the instructions in each block. 188 // Verify phis in join entries and the instructions in each block.
190 for (intptr_t i = 0; i < preorder_.length(); ++i) { 189 for (intptr_t i = 0; i < preorder_.length(); ++i) {
191 BlockEntryInstr* entry = preorder_[i]; 190 BlockEntryInstr* entry = preorder_[i];
192 JoinEntryInstr* join = entry->AsJoinEntry(); 191 JoinEntryInstr* join = entry->AsJoinEntry();
193 if (join != NULL && join->phis() != NULL) { 192 if (join != NULL) {
194 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 193 for (PhiIterator it(join); !it.Done(); it.Advance()) {
195 PhiInstr* phi = (*join->phis())[i]; 194 PhiInstr* phi = it.Current();
196 if (phi != NULL) VerifyUseListsInInstruction(phi); 195 ASSERT(phi != NULL);
196 VerifyUseListsInInstruction(phi);
197 } 197 }
198 } 198 }
199 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 199 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
200 VerifyUseListsInInstruction(it.Current()); 200 VerifyUseListsInInstruction(it.Current());
201 } 201 }
202 } 202 }
203 return true; // Return true so we can ASSERT validation. 203 return true; // Return true so we can ASSERT validation.
204 } 204 }
205 #endif // DEBUG 205 #endif // DEBUG
206 206
207 207
208 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, 208 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number,
209 GrowableArray<Definition*>* inlining_parameters) { 209 GrowableArray<Definition*>* inlining_parameters) {
210 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); 210 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL));
211 current_ssa_temp_index_ = next_virtual_register_number; 211 current_ssa_temp_index_ = next_virtual_register_number;
212 GrowableArray<BitVector*> dominance_frontier; 212 GrowableArray<BitVector*> dominance_frontier;
213 ComputeDominators(&dominance_frontier); 213 ComputeDominators(&dominance_frontier);
214 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 214 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
215 GrowableArray<PhiInstr*> live_phis; 215 GrowableArray<PhiInstr*> live_phis;
216 // Rename uses to reference inserted phis where appropriate. 216 // Rename uses to reference inserted phis where appropriate.
217 // Collect phis that reach a non-environment use. 217 // Collect phis that reach a non-environment use.
218 Rename(&live_phis, inlining_parameters); 218 Rename(&live_phis, inlining_parameters);
219 // Propagate alive mark transitively from alive phis. 219 // Propagate alive mark transitively from alive phis and then remove
220 MarkLivePhis(&live_phis); 220 // non-live ones.
221 RemoveDeadPhis(&live_phis);
221 } 222 }
222 223
223 224
224 // Compute immediate dominators and the dominance frontier for each basic 225 // Compute immediate dominators and the dominance frontier for each basic
225 // block. As a side effect of the algorithm, sets the immediate dominator 226 // block. As a side effect of the algorithm, sets the immediate dominator
226 // of each basic block. 227 // of each basic block.
227 // 228 //
228 // dominance_frontier: an output parameter encoding the dominance frontier. 229 // dominance_frontier: an output parameter encoding the dominance frontier.
229 // The array maps the preorder block number of a block to the set of 230 // The array maps the preorder block number of a block to the set of
230 // (preorder block numbers of) blocks in the dominance frontier. 231 // (preorder block numbers of) blocks in the dominance frontier.
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
571 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 572 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
572 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 573 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
573 ASSERT(pred_index >= 0); 574 ASSERT(pred_index >= 0);
574 if (successor->phis() != NULL) { 575 if (successor->phis() != NULL) {
575 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { 576 for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
576 PhiInstr* phi = (*successor->phis())[i]; 577 PhiInstr* phi = (*successor->phis())[i];
577 if (phi != NULL) { 578 if (phi != NULL) {
578 // Rename input operand. 579 // Rename input operand.
579 Value* use = new Value((*env)[i]); 580 Value* use = new Value((*env)[i]);
580 phi->SetInputAt(pred_index, use); 581 phi->SetInputAt(pred_index, use);
581 use->definition()->AddInputUse(use);
582 } 582 }
583 } 583 }
584 } 584 }
585 } 585 }
586 } 586 }
587 587
588 588
589 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) { 589 void FlowGraph::RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis) {
590 while (!live_phis->is_empty()) { 590 while (!live_phis->is_empty()) {
591 PhiInstr* phi = live_phis->RemoveLast(); 591 PhiInstr* phi = live_phis->RemoveLast();
592 for (intptr_t i = 0; i < phi->InputCount(); i++) { 592 for (intptr_t i = 0; i < phi->InputCount(); i++) {
593 Value* val = phi->InputAt(i); 593 Value* val = phi->InputAt(i);
594 PhiInstr* used_phi = val->definition()->AsPhi(); 594 PhiInstr* used_phi = val->definition()->AsPhi();
595 if ((used_phi != NULL) && !used_phi->is_alive()) { 595 if ((used_phi != NULL) && !used_phi->is_alive()) {
596 used_phi->mark_alive(); 596 used_phi->mark_alive();
597 live_phis->Add(used_phi); 597 live_phis->Add(used_phi);
598 } 598 }
599 } 599 }
600 } 600 }
601
602 for (BlockIterator it(postorder_iterator()); !it.Done(); it.Advance()) {
603 JoinEntryInstr* join = it.Current()->AsJoinEntry();
604 if (join != NULL) join->RemoveDeadPhis(constant_null());
605 }
601 } 606 }
602 607
603 608
604 // Find the natural loop for the back edge m->n and attach loop information 609 // Find the natural loop for the back edge m->n and attach loop information
605 // to block n (loop header). The algorithm is described in "Advanced Compiler 610 // to block n (loop header). The algorithm is described in "Advanced Compiler
606 // Design & Implementation" (Muchnick) p192. 611 // Design & Implementation" (Muchnick) p192.
607 static void FindLoop(BlockEntryInstr* m, 612 static void FindLoop(BlockEntryInstr* m,
608 BlockEntryInstr* n, 613 BlockEntryInstr* n,
609 intptr_t num_blocks) { 614 intptr_t num_blocks) {
610 GrowableArray<BlockEntryInstr*> stack; 615 GrowableArray<BlockEntryInstr*> stack;
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
685 !it.Done(); 690 !it.Done();
686 it.Advance()) { 691 it.Advance()) {
687 ++size; 692 ++size;
688 } 693 }
689 } 694 }
690 return size; 695 return size;
691 } 696 }
692 697
693 698
694 } // namespace dart 699 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698