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 10879036: Compute the def-use list on-demand by walking the dominator tree. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 4 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 Instruction* previous = entry; 57 Instruction* previous = entry;
58 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 58 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
59 Instruction* current = it.Current(); 59 Instruction* current = it.Current();
60 current->set_previous(previous); 60 current->set_previous(previous);
61 previous = current; 61 previous = current;
62 } 62 }
63 } 63 }
64 } 64 }
65 65
66 66
67 #ifdef DEBUG
68 // Helper class to check consistency of the use list construction. Clears all
69 // use-list data in one pass which is then used for assertions when building the
70 // use lists.
71 class DefUseCleanup : public FlowGraphVisitor {
72 public:
73 explicit DefUseCleanup(FlowGraph* flow_graph)
74 : FlowGraphVisitor(flow_graph->preorder()) { }
75 void CleanupInstruction(Instruction* instr) {
76 JoinEntryInstr* join = instr->AsJoinEntry();
77 if (join != NULL && join->phis() != NULL) {
78 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
79 PhiInstr* phi = (*join->phis())[i];
80 if (phi != NULL) CleanupInstruction(phi);
81 }
82 }
83 Definition* defn = instr->AsDefinition();
84 if (defn != NULL) {
85 defn->set_instr_use_list(NULL);
86 defn->set_env_use_list(NULL);
87 }
88 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
89 UseVal* use = instr->InputAt(i)->AsUse();
90 if (use == NULL) continue;
91 use->set_instruction(NULL);
92 use->set_use_index(-1);
93 use->set_next_use(NULL);
94 }
95 if (instr->env() != NULL) {
96 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
97 UseVal* use = instr->env()->values()[i]->AsUse();
98 if (use == NULL) continue;
99 use->set_instruction(NULL);
100 use->set_use_index(-1);
101 use->set_next_use(NULL);
102 }
103 }
104 }
105 #define DEFINE_VISIT(type) \
106 virtual void Visit##type(type##Instr* instr) { CleanupInstruction(instr); }
107 FOR_EACH_INSTRUCTION(DEFINE_VISIT)
108 #undef DEFINE_VISIT
109 };
110 #endif // DEBUG
111
112
113 static void ClearUseLists(Definition* defn) {
114 ASSERT(defn != NULL);
115 ASSERT(defn->instr_use_list() == NULL);
116 ASSERT(defn->env_use_list() == NULL);
117 defn->set_instr_use_list(NULL);
118 defn->set_env_use_list(NULL);
119 }
120
121
122 static void ComputeInstructionUses(Instruction* instr) {
123 ASSERT(instr != NULL);
124 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
125 UseVal* use = instr->InputAt(i)->AsUse();
126 if (use == NULL) continue;
127 ASSERT(use->instruction() == NULL);
128 ASSERT(use->use_index() == -1);
129 ASSERT(use->next_use() == NULL);
130 use->set_instruction(instr);
131 use->set_use_index(i);
132 use->set_next_use(use->definition()->instr_use_list());
133 use->definition()->set_instr_use_list(use);
134 }
135 }
136
137
138 static void ComputeEnvironmentUses(Instruction* instr) {
139 ASSERT(instr != NULL);
140 if (instr->env() == NULL) return;
141 for (intptr_t i = 0; i < instr->env()->values().length(); ++i) {
142 UseVal* use = instr->env()->values()[i]->AsUse();
143 if (use == NULL) continue;
144 ASSERT(use->instruction() == NULL);
145 ASSERT(use->use_index() == -1);
146 ASSERT(use->next_use() == NULL);
147 use->set_instruction(instr);
Vyacheslav Egorov (Google) 2012/08/23 13:51:10 This code for placing use into the list is duplica
zerny-google 2012/08/23 16:11:20 Done. (Added AddToInputUse/AddToEnvUse on UseVal)
148 use->set_use_index(i);
149 use->set_next_use(use->definition()->env_use_list());
150 use->definition()->set_env_use_list(use);
151 }
152 }
153
154
155 static void ComputeUsesInBlock(BlockEntryInstr* block) {
Kevin Millikin (Google) 2012/08/23 13:35:34 Name is not quite right, because it computes uses
zerny-google 2012/08/23 16:11:20 Done.
156 // Clear phi definitions.
157 JoinEntryInstr* join = block->AsJoinEntry();
158 if (join != NULL && join->phis() != NULL) {
159 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
160 PhiInstr* phi = (*join->phis())[i];
161 if (phi != NULL) ClearUseLists(phi);
162 }
163 }
164 // Compute uses on normal instructions.
165 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
166 Instruction* instr = it.Current();
167 if (instr->IsDefinition()) ClearUseLists(instr->AsDefinition());
168 ComputeInstructionUses(instr);
Kevin Millikin (Google) 2012/08/23 13:35:34 Name is not quite right. It sounds like it's comp
zerny-google 2012/08/23 16:11:20 Yes. Similar to this, instr_use has been replaced
169 ComputeEnvironmentUses(instr);
170 }
171 // Compute recursively on dominated blocks.
172 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
173 ComputeUsesInBlock(block->dominated_blocks()[i]);
174 }
175 // Add phi uses on back-edges.
Kevin Millikin (Google) 2012/08/23 13:35:34 Not just back edges, all successor edges.
176 if (block->last_instruction()->SuccessorCount() == 1 &&
177 block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
178 JoinEntryInstr* join =
179 block->last_instruction()->SuccessorAt(0)->AsJoinEntry();
180 intptr_t pred_index = join->IndexOfPredecessor(block);
181 ASSERT(pred_index >= 0);
182 if (join->phis() != NULL) {
183 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
184 PhiInstr* phi = (*join->phis())[i];
185 if (phi == NULL) continue;
186 UseVal* use = phi->InputAt(pred_index)->AsUse();
187 if (use == NULL) continue;
188 ASSERT(use->instruction() == NULL);
189 ASSERT(use->use_index() == -1);
190 ASSERT(use->next_use() == NULL);
191 use->set_instruction(phi);
192 use->set_use_index(pred_index);
193 use->set_next_use(use->definition()->instr_use_list());
194 use->definition()->set_instr_use_list(use);
195 }
196 }
197 }
198 }
199
200
201 bool FlowGraph::ComputeUseLists() {
202 #ifdef DEBUG
203 DefUseCleanup cleanup(this);
Kevin Millikin (Google) 2012/08/23 13:35:34 I don't really like the verification. It's a bit
zerny-google 2012/08/23 16:11:20 I can pull this out, but if so, it is really hard
204 cleanup.VisitBlocks();
205 #endif // DEBUG
206 ComputeUsesInBlock(graph_entry_);
207 return true;
Vyacheslav Egorov (Google) 2012/08/23 13:51:10 what is the reason to have return values which is
208 }
209
210
67 void FlowGraph::ComputeSSA() { 211 void FlowGraph::ComputeSSA() {
68 GrowableArray<BitVector*> dominance_frontier; 212 GrowableArray<BitVector*> dominance_frontier;
69 ComputeDominators(&preorder_, &parent_, &dominance_frontier); 213 ComputeDominators(&preorder_, &parent_, &dominance_frontier);
70 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 214 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
71 GrowableArray<PhiInstr*> live_phis; 215 GrowableArray<PhiInstr*> live_phis;
72 // Rename uses to reference inserted phis where appropriate. 216 // Rename uses to reference inserted phis where appropriate.
73 // Collect phis that reach a non-environment use. 217 // Collect phis that reach a non-environment use.
74 Rename(&live_phis); 218 Rename(&live_phis);
75 // Propagate alive mark transitively from alive phis. 219 // Propagate alive mark transitively from alive phis.
76 MarkLivePhis(&live_phis); 220 MarkLivePhis(&live_phis);
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // Update expression stack. 479 // Update expression stack.
336 ASSERT(env->length() > variable_count()); 480 ASSERT(env->length() > variable_count());
337 481
338 Definition* input_defn = env->Last(); 482 Definition* input_defn = env->Last();
339 env->RemoveLast(); 483 env->RemoveLast();
340 484
341 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); 485 BindInstr* as_bind = v->AsUse()->definition()->AsBind();
342 if ((as_bind != NULL) && 486 if ((as_bind != NULL) &&
343 (as_bind->computation()->IsLoadLocal() || 487 (as_bind->computation()->IsLoadLocal() ||
344 as_bind->computation()->IsStoreLocal())) { 488 as_bind->computation()->IsStoreLocal())) {
345 // Assert exactly one use. 489 // Remove the load/store from the graph.
346 ASSERT(as_bind->use_list() == v);
347 ASSERT(as_bind->use_list()->next_use() == NULL);
348 // Remove the use, its definition and copy the environment value.
349 v->RemoveFromUseList();
350 as_bind->RemoveFromGraph(); 490 as_bind->RemoveFromGraph();
351 // Assert we are not referencing nulls in the initial environment. 491 // Assert we are not referencing nulls in the initial environment.
352 ASSERT(input_defn->ssa_temp_index() != -1); 492 ASSERT(input_defn->ssa_temp_index() != -1);
353 current->SetInputAt(i, new UseVal(input_defn)); 493 current->SetInputAt(i, new UseVal(input_defn));
354 } 494 }
355 } 495 }
356 496
357 // Drop pushed arguments for calls. 497 // Drop pushed arguments for calls.
358 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { 498 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
359 env->RemoveLast(); 499 env->RemoveLast();
(...skipping 20 matching lines...) Expand all
380 index = load->local().BitIndexIn(non_copied_parameter_count_); 520 index = load->local().BitIndexIn(non_copied_parameter_count_);
381 521
382 PhiInstr* phi = (*env)[index]->AsPhi(); 522 PhiInstr* phi = (*env)[index]->AsPhi();
383 if ((phi != NULL) && !phi->is_alive()) { 523 if ((phi != NULL) && !phi->is_alive()) {
384 phi->mark_alive(); 524 phi->mark_alive();
385 live_phis->Add(phi); 525 live_phis->Add(phi);
386 } 526 }
387 } 527 }
388 // Update expression stack or remove from graph. 528 // Update expression stack or remove from graph.
389 if (bind->is_used()) { 529 if (bind->is_used()) {
390 // Assert exactly one use.
391 ASSERT(bind->use_list() != NULL);
392 ASSERT(bind->use_list()->next_use() == NULL);
393 env->Add((*env)[index]); 530 env->Add((*env)[index]);
394 // We remove load/store instructions when we find their use in 2a. 531 // We remove load/store instructions when we find their use in 2a.
395 } else { 532 } else {
396 it.RemoveCurrentFromGraph(); 533 it.RemoveCurrentFromGraph();
397 } 534 }
398 } else { 535 } else {
399 // Not a load or store. 536 // Not a load or store.
400 if (bind->is_used()) { 537 if (bind->is_used()) {
401 // Assign fresh SSA temporary and update expression stack. 538 // Assign fresh SSA temporary and update expression stack.
402 bind->set_ssa_temp_index(alloc_ssa_temp_index()); 539 bind->set_ssa_temp_index(alloc_ssa_temp_index());
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 601 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
465 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 602 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
466 OS::SNPrint(chars, len, kFormat, function_name, reason); 603 OS::SNPrint(chars, len, kFormat, function_name, reason);
467 const Error& error = Error::Handle( 604 const Error& error = Error::Handle(
468 LanguageError::New(String::Handle(String::New(chars)))); 605 LanguageError::New(String::Handle(String::New(chars))));
469 Isolate::Current()->long_jump_base()->Jump(1, error); 606 Isolate::Current()->long_jump_base()->Jump(1, error);
470 } 607 }
471 608
472 609
473 } // namespace dart 610 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698