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

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

Issue 12313033: Revert "Change the SSA construction pass to also construct def-use chains." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 10 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 | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | 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) 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 static intptr_t MembershipCount(Value* use, Value* list) { 118 static intptr_t MembershipCount(Value* use, Value* list) {
119 intptr_t count = 0; 119 intptr_t count = 0;
120 while (list != NULL) { 120 while (list != NULL) {
121 if (list == use) ++count; 121 if (list == use) ++count;
122 list = list->next_use(); 122 list = list->next_use();
123 } 123 }
124 return count; 124 return count;
125 } 125 }
126 126
127 127
128 static void ResetUseListsInInstruction(Instruction* instr) {
129 Definition* defn = instr->AsDefinition();
130 if (defn != NULL) {
131 defn->set_input_use_list(NULL);
132 defn->set_env_use_list(NULL);
133 }
134 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
135 Value* use = instr->InputAt(i);
136 use->set_instruction(NULL);
137 use->set_use_index(-1);
138 use->set_previous_use(NULL);
139 use->set_next_use(NULL);
140 }
141 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
142 Value* use = it.CurrentValue();
143 use->set_instruction(NULL);
144 use->set_use_index(-1);
145 use->set_previous_use(NULL);
146 use->set_next_use(NULL);
147 }
148 }
149
150
151 bool FlowGraph::ResetUseLists() {
152 // Reset initial definitions.
153 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) {
154 ResetUseListsInInstruction((*graph_entry_->initial_definitions())[i]);
155 }
156
157 // Reset phis in join entries and the instructions in each block.
158 for (intptr_t i = 0; i < preorder_.length(); ++i) {
159 BlockEntryInstr* entry = preorder_[i];
160 JoinEntryInstr* join = entry->AsJoinEntry();
161 if (join != NULL && join->phis() != NULL) {
162 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
163 PhiInstr* phi = (*join->phis())[i];
164 if (phi != NULL) ResetUseListsInInstruction(phi);
165 }
166 }
167 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
168 ResetUseListsInInstruction(it.Current());
169 }
170 }
171 return true; // Return true so we can ASSERT the reset code.
172 }
173
174
128 static void VerifyUseListsInInstruction(Instruction* instr) { 175 static void VerifyUseListsInInstruction(Instruction* instr) {
129 ASSERT(instr != NULL); 176 ASSERT(instr != NULL);
130 ASSERT(!instr->IsJoinEntry()); 177 ASSERT(!instr->IsJoinEntry());
131 for (intptr_t i = 0; i < instr->InputCount(); ++i) { 178 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
132 Value* use = instr->InputAt(i); 179 Value* use = instr->InputAt(i);
133 ASSERT(use->definition() != NULL); 180 ASSERT(use->definition() != NULL);
134 ASSERT(use->definition() != instr); 181 ASSERT(use->definition() != instr);
135 ASSERT(use->instruction() == instr); 182 ASSERT(use->instruction() == instr);
136 ASSERT(use->use_index() == i); 183 ASSERT(use->use_index() == i);
137 ASSERT(!FLAG_verify_compiler || 184 ASSERT(!FLAG_verify_compiler ||
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 } 251 }
205 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 252 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
206 VerifyUseListsInInstruction(it.Current()); 253 VerifyUseListsInInstruction(it.Current());
207 } 254 }
208 } 255 }
209 return true; // Return true so we can ASSERT validation. 256 return true; // Return true so we can ASSERT validation.
210 } 257 }
211 #endif // DEBUG 258 #endif // DEBUG
212 259
213 260
261 static void ClearUseLists(Definition* defn) {
262 ASSERT(defn != NULL);
263 ASSERT(!defn->HasUses());
264 defn->set_input_use_list(NULL);
265 defn->set_env_use_list(NULL);
266 }
267
268
269 static void RecordInputUses(Instruction* instr) {
270 ASSERT(instr != NULL);
271 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
272 Value* use = instr->InputAt(i);
273 ASSERT(use->instruction() == NULL);
274 ASSERT(use->use_index() == -1);
275 ASSERT(use->previous_use() == NULL);
276 ASSERT(use->next_use() == NULL);
277 DEBUG_ASSERT(!FLAG_verify_compiler ||
278 (0 == MembershipCount(use, use->definition()->input_use_list())));
279 use->set_instruction(instr);
280 use->set_use_index(i);
281 use->definition()->AddInputUse(use);
282 }
283 }
284
285
286 static void RecordEnvUses(Instruction* instr) {
287 ASSERT(instr != NULL);
288 if (instr->env() == NULL) return;
289 intptr_t use_index = 0;
290 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
291 Value* use = it.CurrentValue();
292 ASSERT(use->instruction() == NULL);
293 ASSERT(use->use_index() == -1);
294 ASSERT(use->previous_use() == NULL);
295 ASSERT(use->next_use() == NULL);
296 DEBUG_ASSERT(!FLAG_verify_compiler ||
297 (0 == MembershipCount(use, use->definition()->env_use_list())));
298 use->set_instruction(instr);
299 use->set_use_index(use_index++);
300 use->definition()->AddEnvUse(use);
301 }
302 }
303
304
305 static void ComputeUseListsRecursive(BlockEntryInstr* block) {
306 // Clear phi definitions.
307 JoinEntryInstr* join = block->AsJoinEntry();
308 if (join != NULL && join->phis() != NULL) {
309 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
310 PhiInstr* phi = (*join->phis())[i];
311 if (phi != NULL) ClearUseLists(phi);
312 }
313 }
314 // Compute uses on normal instructions.
315 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
316 Instruction* instr = it.Current();
317 if (instr->IsDefinition()) ClearUseLists(instr->AsDefinition());
318 RecordInputUses(instr);
319 RecordEnvUses(instr);
320 }
321 // Compute recursively on dominated blocks.
322 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
323 ComputeUseListsRecursive(block->dominated_blocks()[i]);
324 }
325 // Add phi uses on successor edges.
326 if (block->last_instruction()->SuccessorCount() == 1 &&
327 block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
328 JoinEntryInstr* join =
329 block->last_instruction()->SuccessorAt(0)->AsJoinEntry();
330 intptr_t pred_index = join->IndexOfPredecessor(block);
331 ASSERT(pred_index >= 0);
332 if (join->phis() != NULL) {
333 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
334 PhiInstr* phi = (*join->phis())[i];
335 if (phi == NULL) continue;
336 Value* use = phi->InputAt(pred_index);
337 ASSERT(use->instruction() == NULL);
338 ASSERT(use->use_index() == -1);
339 ASSERT(use->previous_use() == NULL);
340 ASSERT(use->next_use() == NULL);
341 DEBUG_ASSERT(!FLAG_verify_compiler ||
342 (0 == MembershipCount(use, use->definition()->input_use_list())));
343 use->set_instruction(phi);
344 use->set_use_index(pred_index);
345 use->definition()->AddInputUse(use);
346 }
347 }
348 }
349 }
350
351
352 void FlowGraph::ComputeUseLists() {
353 DEBUG_ASSERT(ResetUseLists());
354 // Clear initial definitions.
355 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) {
356 ClearUseLists((*graph_entry_->initial_definitions())[i]);
357 }
358 ComputeUseListsRecursive(graph_entry_);
359 DEBUG_ASSERT(!FLAG_verify_compiler || VerifyUseLists());
360 }
361
362
214 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, 363 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number,
215 GrowableArray<Definition*>* inlining_parameters) { 364 GrowableArray<Definition*>* inlining_parameters) {
216 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); 365 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL));
217 current_ssa_temp_index_ = next_virtual_register_number; 366 current_ssa_temp_index_ = next_virtual_register_number;
218 GrowableArray<BitVector*> dominance_frontier; 367 GrowableArray<BitVector*> dominance_frontier;
219 ComputeDominators(&dominance_frontier); 368 ComputeDominators(&dominance_frontier);
220 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 369 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
221 GrowableArray<PhiInstr*> live_phis; 370 GrowableArray<PhiInstr*> live_phis;
222 // Rename uses to reference inserted phis where appropriate. 371 // Rename uses to reference inserted phis where appropriate.
223 // Collect phis that reach a non-environment use. 372 // Collect phis that reach a non-environment use.
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 } 612 }
464 } 613 }
465 614
466 // 2. Process normal instructions. 615 // 2. Process normal instructions.
467 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 616 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
468 Instruction* current = it.Current(); 617 Instruction* current = it.Current();
469 // Attach current environment to the instructions that can deoptimize and 618 // Attach current environment to the instructions that can deoptimize and
470 // at goto instructions. Optimizations like LICM expect an environment at 619 // at goto instructions. Optimizations like LICM expect an environment at
471 // gotos. 620 // gotos.
472 if (current->CanDeoptimize() || current->IsGoto()) { 621 if (current->CanDeoptimize() || current->IsGoto()) {
473 Environment* deopt_env = 622 current->set_env(Environment::From(*env,
474 Environment::From(*env, 623 num_non_copied_params_,
475 num_non_copied_params_, 624 parsed_function_.function()));
476 parsed_function_.function());
477 current->set_env(deopt_env);
478 intptr_t use_index = 0;
479 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
480 Value* use = it.CurrentValue();
481 use->set_instruction(current);
482 use->set_use_index(use_index++);
483 use->definition()->AddEnvUse(use);
484 }
485 } 625 }
486 if (current->CanDeoptimize()) { 626 if (current->CanDeoptimize()) {
487 current->env()->set_deopt_id(current->deopt_id()); 627 current->env()->set_deopt_id(current->deopt_id());
488 } 628 }
489 629
490 // 2a. Handle uses: 630 // 2a. Handle uses:
491 // Update expression stack environment for each use. 631 // Update expression stack environment for each use.
492 // For each use of a LoadLocal or StoreLocal: Replace it with the value 632 // For each use of a LoadLocal or StoreLocal: Replace it with the value
493 // from the environment. 633 // from the environment.
494 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { 634 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
495 Value* v = current->InputAt(i); 635 Value* v = current->InputAt(i);
496 // Update expression stack. 636 // Update expression stack.
497 ASSERT(env->length() > variable_count()); 637 ASSERT(env->length() > variable_count());
498 638
499 Definition* reaching_defn = env->RemoveLast(); 639 Definition* reaching_defn = env->RemoveLast();
500 640
501 Definition* input_defn = v->definition(); 641 Definition* input_defn = v->definition();
502 if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) { 642 if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) {
503 // Remove the load/store from the graph. 643 // Remove the load/store from the graph.
504 input_defn->UnuseAllInputs();
505 input_defn->RemoveFromGraph(); 644 input_defn->RemoveFromGraph();
506 // Assert we are not referencing nulls in the initial environment. 645 // Assert we are not referencing nulls in the initial environment.
507 ASSERT(reaching_defn->ssa_temp_index() != -1); 646 ASSERT(reaching_defn->ssa_temp_index() != -1);
508 v->set_definition(reaching_defn); 647 current->SetInputAt(i, new Value(reaching_defn));
509 input_defn = reaching_defn;
510 } 648 }
511 v->set_instruction(current);
512 v->set_use_index(i);
513 input_defn->AddInputUse(v);
514 } 649 }
515 650
516 // Drop pushed arguments for calls. 651 // Drop pushed arguments for calls.
517 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { 652 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
518 env->RemoveLast(); 653 env->RemoveLast();
519 } 654 }
520 655
521 // 2b. Handle LoadLocal and StoreLocal. 656 // 2b. Handle LoadLocal and StoreLocal.
522 // For each LoadLocal: Remove it from the graph. 657 // For each LoadLocal: Remove it from the graph.
523 // For each StoreLocal: Remove it from the graph and update the environment. 658 // For each StoreLocal: Remove it from the graph and update the environment.
(...skipping 17 matching lines...) Expand all
541 if ((phi != NULL) && !phi->is_alive()) { 676 if ((phi != NULL) && !phi->is_alive()) {
542 phi->mark_alive(); 677 phi->mark_alive();
543 live_phis->Add(phi); 678 live_phis->Add(phi);
544 } 679 }
545 } 680 }
546 // Update expression stack or remove from graph. 681 // Update expression stack or remove from graph.
547 if (definition->is_used()) { 682 if (definition->is_used()) {
548 env->Add((*env)[index]); 683 env->Add((*env)[index]);
549 // We remove load/store instructions when we find their use in 2a. 684 // We remove load/store instructions when we find their use in 2a.
550 } else { 685 } else {
551 definition->UnuseAllInputs();
552 it.RemoveCurrentFromGraph(); 686 it.RemoveCurrentFromGraph();
553 } 687 }
554 } else { 688 } else {
555 // Not a load or store. 689 // Not a load or store.
556 if (definition->is_used()) { 690 if (definition->is_used()) {
557 // Assign fresh SSA temporary and update expression stack. 691 // Assign fresh SSA temporary and update expression stack.
558 definition->set_ssa_temp_index(alloc_ssa_temp_index()); 692 definition->set_ssa_temp_index(alloc_ssa_temp_index());
559 env->Add(definition); 693 env->Add(definition);
560 } 694 }
561 } 695 }
(...skipping 20 matching lines...) Expand all
582 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 716 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
583 JoinEntryInstr* successor = 717 JoinEntryInstr* successor =
584 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 718 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
585 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 719 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
586 ASSERT(pred_index >= 0); 720 ASSERT(pred_index >= 0);
587 if (successor->phis() != NULL) { 721 if (successor->phis() != NULL) {
588 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { 722 for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
589 PhiInstr* phi = (*successor->phis())[i]; 723 PhiInstr* phi = (*successor->phis())[i];
590 if (phi != NULL) { 724 if (phi != NULL) {
591 // Rename input operand. 725 // Rename input operand.
592 Value* use = new Value((*env)[i]); 726 phi->SetInputAt(pred_index, new Value((*env)[i]));
593 phi->SetInputAt(pred_index, use);
594 use->set_instruction(phi);
595 use->set_use_index(pred_index);
596 use->definition()->AddInputUse(use);
597 } 727 }
598 } 728 }
599 } 729 }
600 } 730 }
601 } 731 }
602 732
603 733
604 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) { 734 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) {
605 while (!live_phis->is_empty()) { 735 while (!live_phis->is_empty()) {
606 PhiInstr* phi = live_phis->RemoveLast(); 736 PhiInstr* phi = live_phis->RemoveLast();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 !it.Done(); 830 !it.Done();
701 it.Advance()) { 831 it.Advance()) {
702 ++size; 832 ++size;
703 } 833 }
704 } 834 }
705 return size; 835 return size;
706 } 836 }
707 837
708 838
709 } // namespace dart 839 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_builder.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698