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

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

Issue 12326012: 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
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
175 static void VerifyUseListsInInstruction(Instruction* instr) { 128 static void VerifyUseListsInInstruction(Instruction* instr) {
176 ASSERT(instr != NULL); 129 ASSERT(instr != NULL);
177 ASSERT(!instr->IsJoinEntry()); 130 ASSERT(!instr->IsJoinEntry());
178 for (intptr_t i = 0; i < instr->InputCount(); ++i) { 131 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
179 Value* use = instr->InputAt(i); 132 Value* use = instr->InputAt(i);
180 ASSERT(use->definition() != NULL); 133 ASSERT(use->definition() != NULL);
181 ASSERT(use->definition() != instr); 134 ASSERT(use->definition() != instr);
182 ASSERT(use->instruction() == instr); 135 ASSERT(use->instruction() == instr);
183 ASSERT(use->use_index() == i); 136 ASSERT(use->use_index() == i);
184 ASSERT(!FLAG_verify_compiler || 137 ASSERT(!FLAG_verify_compiler ||
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 } 204 }
252 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 205 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
253 VerifyUseListsInInstruction(it.Current()); 206 VerifyUseListsInInstruction(it.Current());
254 } 207 }
255 } 208 }
256 return true; // Return true so we can ASSERT validation. 209 return true; // Return true so we can ASSERT validation.
257 } 210 }
258 #endif // DEBUG 211 #endif // DEBUG
259 212
260 213
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
363 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, 214 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number,
364 GrowableArray<Definition*>* inlining_parameters) { 215 GrowableArray<Definition*>* inlining_parameters) {
365 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); 216 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL));
366 current_ssa_temp_index_ = next_virtual_register_number; 217 current_ssa_temp_index_ = next_virtual_register_number;
367 GrowableArray<BitVector*> dominance_frontier; 218 GrowableArray<BitVector*> dominance_frontier;
368 ComputeDominators(&dominance_frontier); 219 ComputeDominators(&dominance_frontier);
369 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 220 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
370 GrowableArray<PhiInstr*> live_phis; 221 GrowableArray<PhiInstr*> live_phis;
371 // Rename uses to reference inserted phis where appropriate. 222 // Rename uses to reference inserted phis where appropriate.
372 // Collect phis that reach a non-environment use. 223 // Collect phis that reach a non-environment use.
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 } 463 }
613 } 464 }
614 465
615 // 2. Process normal instructions. 466 // 2. Process normal instructions.
616 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { 467 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
617 Instruction* current = it.Current(); 468 Instruction* current = it.Current();
618 // Attach current environment to the instructions that can deoptimize and 469 // Attach current environment to the instructions that can deoptimize and
619 // at goto instructions. Optimizations like LICM expect an environment at 470 // at goto instructions. Optimizations like LICM expect an environment at
620 // gotos. 471 // gotos.
621 if (current->CanDeoptimize() || current->IsGoto()) { 472 if (current->CanDeoptimize() || current->IsGoto()) {
622 current->set_env(Environment::From(*env, 473 Environment* deopt_env =
623 num_non_copied_params_, 474 Environment::From(*env,
624 parsed_function_.function())); 475 num_non_copied_params_,
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 }
625 } 485 }
626 if (current->CanDeoptimize()) { 486 if (current->CanDeoptimize()) {
627 current->env()->set_deopt_id(current->deopt_id()); 487 current->env()->set_deopt_id(current->deopt_id());
628 } 488 }
629 489
630 // 2a. Handle uses: 490 // 2a. Handle uses:
631 // Update expression stack environment for each use. 491 // Update expression stack environment for each use.
632 // For each use of a LoadLocal or StoreLocal: Replace it with the value 492 // For each use of a LoadLocal or StoreLocal: Replace it with the value
633 // from the environment. 493 // from the environment.
634 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { 494 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
635 Value* v = current->InputAt(i); 495 Value* v = current->InputAt(i);
636 // Update expression stack. 496 // Update expression stack.
637 ASSERT(env->length() > variable_count()); 497 ASSERT(env->length() > variable_count());
638 498
639 Definition* reaching_defn = env->RemoveLast(); 499 Definition* reaching_defn = env->RemoveLast();
640 500
641 Definition* input_defn = v->definition(); 501 Definition* input_defn = v->definition();
642 if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) { 502 if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) {
643 // Remove the load/store from the graph. 503 // Remove the load/store from the graph.
504 input_defn->UnuseAllInputs();
644 input_defn->RemoveFromGraph(); 505 input_defn->RemoveFromGraph();
645 // Assert we are not referencing nulls in the initial environment. 506 // Assert we are not referencing nulls in the initial environment.
646 ASSERT(reaching_defn->ssa_temp_index() != -1); 507 ASSERT(reaching_defn->ssa_temp_index() != -1);
647 current->SetInputAt(i, new Value(reaching_defn)); 508 v->set_definition(reaching_defn);
509 input_defn = reaching_defn;
648 } 510 }
511 v->set_instruction(current);
512 v->set_use_index(i);
513 input_defn->AddInputUse(v);
649 } 514 }
650 515
651 // Drop pushed arguments for calls. 516 // Drop pushed arguments for calls.
652 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { 517 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
653 env->RemoveLast(); 518 env->RemoveLast();
654 } 519 }
655 520
656 // 2b. Handle LoadLocal and StoreLocal. 521 // 2b. Handle LoadLocal and StoreLocal.
657 // For each LoadLocal: Remove it from the graph. 522 // For each LoadLocal: Remove it from the graph.
658 // For each StoreLocal: Remove it from the graph and update the environment. 523 // For each StoreLocal: Remove it from the graph and update the environment.
(...skipping 17 matching lines...) Expand all
676 if ((phi != NULL) && !phi->is_alive()) { 541 if ((phi != NULL) && !phi->is_alive()) {
677 phi->mark_alive(); 542 phi->mark_alive();
678 live_phis->Add(phi); 543 live_phis->Add(phi);
679 } 544 }
680 } 545 }
681 // Update expression stack or remove from graph. 546 // Update expression stack or remove from graph.
682 if (definition->is_used()) { 547 if (definition->is_used()) {
683 env->Add((*env)[index]); 548 env->Add((*env)[index]);
684 // We remove load/store instructions when we find their use in 2a. 549 // We remove load/store instructions when we find their use in 2a.
685 } else { 550 } else {
551 definition->UnuseAllInputs();
686 it.RemoveCurrentFromGraph(); 552 it.RemoveCurrentFromGraph();
687 } 553 }
688 } else { 554 } else {
689 // Not a load or store. 555 // Not a load or store.
690 if (definition->is_used()) { 556 if (definition->is_used()) {
691 // Assign fresh SSA temporary and update expression stack. 557 // Assign fresh SSA temporary and update expression stack.
692 definition->set_ssa_temp_index(alloc_ssa_temp_index()); 558 definition->set_ssa_temp_index(alloc_ssa_temp_index());
693 env->Add(definition); 559 env->Add(definition);
694 } 560 }
695 } 561 }
(...skipping 20 matching lines...) Expand all
716 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 582 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
717 JoinEntryInstr* successor = 583 JoinEntryInstr* successor =
718 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 584 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
719 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 585 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
720 ASSERT(pred_index >= 0); 586 ASSERT(pred_index >= 0);
721 if (successor->phis() != NULL) { 587 if (successor->phis() != NULL) {
722 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { 588 for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
723 PhiInstr* phi = (*successor->phis())[i]; 589 PhiInstr* phi = (*successor->phis())[i];
724 if (phi != NULL) { 590 if (phi != NULL) {
725 // Rename input operand. 591 // Rename input operand.
726 phi->SetInputAt(pred_index, new Value((*env)[i])); 592 Value* use = 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);
727 } 597 }
728 } 598 }
729 } 599 }
730 } 600 }
731 } 601 }
732 602
733 603
734 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) { 604 void FlowGraph::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) {
735 while (!live_phis->is_empty()) { 605 while (!live_phis->is_empty()) {
736 PhiInstr* phi = live_phis->RemoveLast(); 606 PhiInstr* phi = live_phis->RemoveLast();
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 !it.Done(); 700 !it.Done();
831 it.Advance()) { 701 it.Advance()) {
832 ++size; 702 ++size;
833 } 703 }
834 } 704 }
835 return size; 705 return size;
836 } 706 }
837 707
838 708
839 } // namespace dart 709 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698