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

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

Issue 10946027: Revert "Initial implementation of sparse conditional constant propagation." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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 | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_optimizer.h » ('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 16 matching lines...) Expand all
27 preorder_(), 27 preorder_(),
28 postorder_(), 28 postorder_(),
29 reverse_postorder_(), 29 reverse_postorder_(),
30 exits_(NULL) { 30 exits_(NULL) {
31 DiscoverBlocks(); 31 DiscoverBlocks();
32 } 32 }
33 33
34 34
35 void FlowGraph::DiscoverBlocks() { 35 void FlowGraph::DiscoverBlocks() {
36 // Initialize state. 36 // Initialize state.
37 preorder_.Clear(); 37 preorder_.TruncateTo(0);
38 postorder_.Clear(); 38 postorder_.TruncateTo(0);
39 reverse_postorder_.Clear(); 39 reverse_postorder_.TruncateTo(0);
40 parent_.Clear(); 40 parent_.TruncateTo(0);
41 assigned_vars_.Clear(); 41 assigned_vars_.TruncateTo(0);
42 // Perform a depth-first traversal of the graph to build preorder and 42 // Perform a depth-first traversal of the graph to build preorder and
43 // postorder block orders. 43 // postorder block orders.
44 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor. 44 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor.
45 &preorder_, 45 &preorder_,
46 &postorder_, 46 &postorder_,
47 &parent_, 47 &parent_,
48 &assigned_vars_, 48 &assigned_vars_,
49 variable_count(), 49 variable_count(),
50 num_non_copied_params()); 50 num_non_copied_params());
51 // Number blocks in reverse postorder. 51 // Number blocks in reverse postorder.
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 ValidateUseListsInInstruction(it.Current()); 191 ValidateUseListsInInstruction(it.Current());
192 } 192 }
193 } 193 }
194 return true; // Return true so we can ASSERT validation. 194 return true; // Return true so we can ASSERT validation.
195 } 195 }
196 #endif // DEBUG 196 #endif // DEBUG
197 197
198 198
199 static void ClearUseLists(Definition* defn) { 199 static void ClearUseLists(Definition* defn) {
200 ASSERT(defn != NULL); 200 ASSERT(defn != NULL);
201 ASSERT(defn->input_use_list() == NULL); 201 DEBUG_ASSERT(defn->input_use_list() == NULL);
202 ASSERT(defn->env_use_list() == NULL); 202 DEBUG_ASSERT(defn->env_use_list() == NULL);
203 defn->set_input_use_list(NULL); 203 defn->set_input_use_list(NULL);
204 defn->set_env_use_list(NULL); 204 defn->set_env_use_list(NULL);
205 } 205 }
206 206
207 207
208 static void RecordInputUses(Instruction* instr) { 208 static void RecordInputUses(Instruction* instr) {
209 ASSERT(instr != NULL); 209 ASSERT(instr != NULL);
210 for (intptr_t i = 0; i < instr->InputCount(); ++i) { 210 for (intptr_t i = 0; i < instr->InputCount(); ++i) {
211 Value* use = instr->InputAt(i); 211 Value* use = instr->InputAt(i);
212 ASSERT(use->instruction() == NULL); 212 DEBUG_ASSERT(use->instruction() == NULL);
213 ASSERT(use->use_index() == -1); 213 DEBUG_ASSERT(use->use_index() == -1);
214 ASSERT(use->next_use() == NULL); 214 DEBUG_ASSERT(use->next_use() == NULL);
215 DEBUG_ASSERT(0 == MembershipCount(use, 215 DEBUG_ASSERT(0 == MembershipCount(use,
216 use->definition()->input_use_list())); 216 use->definition()->input_use_list()));
217 use->set_instruction(instr); 217 use->set_instruction(instr);
218 use->set_use_index(i); 218 use->set_use_index(i);
219 use->AddToInputUseList(); 219 use->AddToInputUseList();
220 } 220 }
221 } 221 }
222 222
223 223
224 static void RecordEnvUses(Instruction* instr) { 224 static void RecordEnvUses(Instruction* instr) {
225 ASSERT(instr != NULL); 225 ASSERT(instr != NULL);
226 if (instr->env() == NULL) return; 226 if (instr->env() == NULL) return;
227 intptr_t use_index = 0; 227 intptr_t use_index = 0;
228 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) { 228 for (Environment::DeepIterator it(instr->env()); !it.Done(); it.Advance()) {
229 Value* use = it.CurrentValue(); 229 Value* use = it.CurrentValue();
230 ASSERT(use->instruction() == NULL); 230 DEBUG_ASSERT(use->instruction() == NULL);
231 ASSERT(use->use_index() == -1); 231 DEBUG_ASSERT(use->use_index() == -1);
232 ASSERT(use->next_use() == NULL); 232 DEBUG_ASSERT(use->next_use() == NULL);
233 DEBUG_ASSERT(0 == MembershipCount(use, use->definition()->env_use_list())); 233 DEBUG_ASSERT(0 == MembershipCount(use, use->definition()->env_use_list()));
234 use->set_instruction(instr); 234 use->set_instruction(instr);
235 use->set_use_index(use_index++); 235 use->set_use_index(use_index++);
236 use->AddToEnvUseList(); 236 use->AddToEnvUseList();
237 } 237 }
238 } 238 }
239 239
240 240
241 static void ComputeUseListsRecursive(BlockEntryInstr* block) { 241 static void ComputeUseListsRecursive(BlockEntryInstr* block) {
242 // Clear phi definitions. 242 // Clear phi definitions.
(...skipping 20 matching lines...) Expand all
263 block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 263 block->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
264 JoinEntryInstr* join = 264 JoinEntryInstr* join =
265 block->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 265 block->last_instruction()->SuccessorAt(0)->AsJoinEntry();
266 intptr_t pred_index = join->IndexOfPredecessor(block); 266 intptr_t pred_index = join->IndexOfPredecessor(block);
267 ASSERT(pred_index >= 0); 267 ASSERT(pred_index >= 0);
268 if (join->phis() != NULL) { 268 if (join->phis() != NULL) {
269 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 269 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
270 PhiInstr* phi = (*join->phis())[i]; 270 PhiInstr* phi = (*join->phis())[i];
271 if (phi == NULL) continue; 271 if (phi == NULL) continue;
272 Value* use = phi->InputAt(pred_index); 272 Value* use = phi->InputAt(pred_index);
273 ASSERT(use->instruction() == NULL); 273 DEBUG_ASSERT(use->instruction() == NULL);
274 ASSERT(use->use_index() == -1); 274 DEBUG_ASSERT(use->use_index() == -1);
275 ASSERT(use->next_use() == NULL); 275 DEBUG_ASSERT(use->next_use() == NULL);
276 DEBUG_ASSERT(0 == MembershipCount(use, 276 DEBUG_ASSERT(0 == MembershipCount(use,
277 use->definition()->input_use_list())); 277 use->definition()->input_use_list()));
278 use->set_instruction(phi); 278 use->set_instruction(phi);
279 use->set_use_index(pred_index); 279 use->set_use_index(pred_index);
280 use->AddToInputUseList(); 280 use->AddToInputUseList();
281 } 281 }
282 } 282 }
283 } 283 }
284 } 284 }
285 285
286 286
287 void FlowGraph::ComputeUseLists() { 287 void FlowGraph::ComputeUseLists() {
288 DEBUG_ASSERT(ResetUseLists()); 288 DEBUG_ASSERT(ResetUseLists());
289 // Clear global constants and definitions in the start environment. 289 // Clear global constants and definitions in the start environment.
290 ClearUseLists(graph_entry_->constant_null()); 290 ClearUseLists(graph_entry_->constant_null());
291 for (intptr_t i = 0; i < graph_entry_->start_env()->Length(); ++i) { 291 for (intptr_t i = 0; i < graph_entry_->start_env()->Length(); ++i) {
292 ClearUseLists(graph_entry_->start_env()->ValueAt(i)->definition()); 292 ClearUseLists(graph_entry_->start_env()->ValueAt(i)->definition());
293 } 293 }
294 ComputeUseListsRecursive(graph_entry_); 294 ComputeUseListsRecursive(graph_entry_);
295 DEBUG_ASSERT(ValidateUseLists()); 295 DEBUG_ASSERT(ValidateUseLists());
296 } 296 }
297 297
298 298
299 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number) { 299 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number) {
300 current_ssa_temp_index_ = next_virtual_register_number; 300 current_ssa_temp_index_ = next_virtual_register_number;
301 GrowableArray<BitVector*> dominance_frontier; 301 GrowableArray<BitVector*> dominance_frontier;
302 ComputeDominators(&dominance_frontier); 302 ComputeDominators(&preorder_, &parent_, &dominance_frontier);
303 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 303 InsertPhis(preorder_, assigned_vars_, dominance_frontier);
304 GrowableArray<PhiInstr*> live_phis; 304 GrowableArray<PhiInstr*> live_phis;
305 // Rename uses to reference inserted phis where appropriate. 305 // Rename uses to reference inserted phis where appropriate.
306 // Collect phis that reach a non-environment use. 306 // Collect phis that reach a non-environment use.
307 Rename(&live_phis); 307 Rename(&live_phis);
308 // Propagate alive mark transitively from alive phis. 308 // Propagate alive mark transitively from alive phis.
309 MarkLivePhis(&live_phis); 309 MarkLivePhis(&live_phis);
310 } 310 }
311 311
312 312
313 // Compute immediate dominators and the dominance frontier for each basic 313 // Compute immediate dominators and the dominance frontier for each basic
314 // block. As a side effect of the algorithm, sets the immediate dominator 314 // block. As a side effect of the algorithm, sets the immediate dominator
315 // of each basic block. 315 // of each basic block.
316 // 316 //
317 // preorder: an input list of basic block entries in preorder. The
318 // algorithm relies on the block ordering.
319 //
320 // parent: an input parameter encoding a depth-first spanning tree of
321 // the control flow graph. The array maps the preorder block
322 // number of a block to the preorder block number of its spanning
323 // tree parent.
324 //
317 // dominance_frontier: an output parameter encoding the dominance frontier. 325 // dominance_frontier: an output parameter encoding the dominance frontier.
318 // The array maps the preorder block number of a block to the set of 326 // The array maps the preorder block number of a block to the set of
319 // (preorder block numbers of) blocks in the dominance frontier. 327 // (preorder block numbers of) blocks in the dominance frontier.
320 void FlowGraph::ComputeDominators( 328 void FlowGraph::ComputeDominators(
329 GrowableArray<BlockEntryInstr*>* preorder,
330 GrowableArray<intptr_t>* parent,
321 GrowableArray<BitVector*>* dominance_frontier) { 331 GrowableArray<BitVector*>* dominance_frontier) {
322 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass 332 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
323 // version of the Lengauer-Tarjan algorithm (LT is normally three passes) 333 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
324 // that eliminates a pass by using nearest-common ancestor (NCA) to 334 // that eliminates a pass by using nearest-common ancestor (NCA) to
325 // compute immediate dominators from semidominators. It also removes a 335 // compute immediate dominators from semidominators. It also removes a
326 // level of indirection in the link-eval forest data structure. 336 // level of indirection in the link-eval forest data structure.
327 // 337 //
328 // The algorithm is described in Georgiadis, Tarjan, and Werneck's 338 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
329 // "Finding Dominators in Practice". 339 // "Finding Dominators in Practice".
330 // See http://www.cs.princeton.edu/~rwerneck/dominators/ . 340 // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
331 341
332 // All arrays are maps between preorder basic-block numbers. 342 // All arrays are maps between preorder basic-block numbers.
333 intptr_t size = parent_.length(); 343 intptr_t size = parent->length();
334 GrowableArray<intptr_t> idom(size); // Immediate dominator. 344 GrowableArray<intptr_t> idom(size); // Immediate dominator.
335 GrowableArray<intptr_t> semi(size); // Semidominator. 345 GrowableArray<intptr_t> semi(size); // Semidominator.
336 GrowableArray<intptr_t> label(size); // Label for link-eval forest. 346 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
337 347
338 // 1. First pass: compute semidominators as in Lengauer-Tarjan. 348 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
339 // Semidominators are computed from a depth-first spanning tree and are an 349 // Semidominators are computed from a depth-first spanning tree and are an
340 // approximation of immediate dominators. 350 // approximation of immediate dominators.
341 351
342 // Use a link-eval data structure with path compression. Implement path 352 // Use a link-eval data structure with path compression. Implement path
343 // compression in place by mutating the parent array. Each block has a 353 // compression in place by mutating the parent array. Each block has a
344 // label, which is the minimum block number on the compressed path. 354 // label, which is the minimum block number on the compressed path.
345 355
346 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the 356 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
347 // dominance frontier output array. 357 // dominance frontier output array.
348 for (intptr_t i = 0; i < size; ++i) { 358 for (intptr_t i = 0; i < size; ++i) {
349 idom.Add(parent_[i]); 359 idom.Add((*parent)[i]);
350 semi.Add(i); 360 semi.Add(i);
351 label.Add(i); 361 label.Add(i);
352 dominance_frontier->Add(new BitVector(size)); 362 dominance_frontier->Add(new BitVector(size));
353 } 363 }
354 364
355 // Loop over the blocks in reverse preorder (not including the graph 365 // Loop over the blocks in reverse preorder (not including the graph
356 // entry). Clear the dominated blocks in the graph entry in case 366 // entry).
357 // ComputeDominators is used to recompute them.
358 preorder_[0]->ClearDominatedBlocks();
359 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) { 367 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
360 // Loop over the predecessors. 368 // Loop over the predecessors.
361 BlockEntryInstr* block = preorder_[block_index]; 369 BlockEntryInstr* block = (*preorder)[block_index];
362 // Clear the immediately dominated blocks in case ComputeDominators is
363 // used to recompute them.
364 block->ClearDominatedBlocks();
365 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { 370 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
366 BlockEntryInstr* pred = block->PredecessorAt(i); 371 BlockEntryInstr* pred = block->PredecessorAt(i);
367 ASSERT(pred != NULL); 372 ASSERT(pred != NULL);
368 373
369 // Look for the semidominator by ascending the semidominator path 374 // Look for the semidominator by ascending the semidominator path
370 // starting from pred. 375 // starting from pred.
371 intptr_t pred_index = pred->preorder_number(); 376 intptr_t pred_index = pred->preorder_number();
372 intptr_t best = pred_index; 377 intptr_t best = pred_index;
373 if (pred_index > block_index) { 378 if (pred_index > block_index) {
374 CompressPath(block_index, pred_index, &parent_, &label); 379 CompressPath(block_index, pred_index, parent, &label);
375 best = label[pred_index]; 380 best = label[pred_index];
376 } 381 }
377 382
378 // Update the semidominator if we've found a better one. 383 // Update the semidominator if we've found a better one.
379 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]); 384 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
380 } 385 }
381 386
382 // Now use label for the semidominator. 387 // Now use label for the semidominator.
383 label[block_index] = semi[block_index]; 388 label[block_index] = semi[block_index];
384 } 389 }
385 390
386 // 2. Compute the immediate dominators as the nearest common ancestor of 391 // 2. Compute the immediate dominators as the nearest common ancestor of
387 // spanning tree parent and semidominator, for all blocks except the entry. 392 // spanning tree parent and semidominator, for all blocks except the entry.
388 for (intptr_t block_index = 1; block_index < size; ++block_index) { 393 for (intptr_t block_index = 1; block_index < size; ++block_index) {
389 intptr_t dom_index = idom[block_index]; 394 intptr_t dom_index = idom[block_index];
390 while (dom_index > semi[block_index]) { 395 while (dom_index > semi[block_index]) {
391 dom_index = idom[dom_index]; 396 dom_index = idom[dom_index];
392 } 397 }
393 idom[block_index] = dom_index; 398 idom[block_index] = dom_index;
394 preorder_[block_index]->set_dominator(preorder_[dom_index]); 399 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]);
395 preorder_[dom_index]->AddDominatedBlock(preorder_[block_index]); 400 (*preorder)[dom_index]->AddDominatedBlock((*preorder)[block_index]);
396 } 401 }
397 402
398 // 3. Now compute the dominance frontier for all blocks. This is 403 // 3. Now compute the dominance frontier for all blocks. This is
399 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is 404 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is
400 // attributed to a paper by Ferrante et al. There is no bookkeeping 405 // attributed to a paper by Ferrante et al. There is no bookkeeping
401 // required to avoid adding a block twice to the same block's dominance 406 // required to avoid adding a block twice to the same block's dominance
402 // frontier because we use a set to represent the dominance frontier. 407 // frontier because we use a set to represent the dominance frontier.
403 for (intptr_t block_index = 0; block_index < size; ++block_index) { 408 for (intptr_t block_index = 0; block_index < size; ++block_index) {
404 BlockEntryInstr* block = preorder_[block_index]; 409 BlockEntryInstr* block = (*preorder)[block_index];
405 intptr_t count = block->PredecessorCount(); 410 intptr_t count = block->PredecessorCount();
406 if (count <= 1) continue; 411 if (count <= 1) continue;
407 for (intptr_t i = 0; i < count; ++i) { 412 for (intptr_t i = 0; i < count; ++i) {
408 BlockEntryInstr* runner = block->PredecessorAt(i); 413 BlockEntryInstr* runner = block->PredecessorAt(i);
409 while (runner != block->dominator()) { 414 while (runner != block->dominator()) {
410 (*dominance_frontier)[runner->preorder_number()]->Add(block_index); 415 (*dominance_frontier)[runner->preorder_number()]->Add(block_index);
411 runner = runner->dominator(); 416 runner = runner->dominator();
412 } 417 }
413 } 418 }
414 } 419 }
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 // TODO(zerny): Support multiple exits. 807 // TODO(zerny): Support multiple exits.
803 UNREACHABLE(); 808 UNREACHABLE();
804 } 809 }
805 810
806 // TODO(zerny): Adjust pre/post orders. 811 // TODO(zerny): Adjust pre/post orders.
807 // TODO(zerny): Update dominator tree. 812 // TODO(zerny): Update dominator tree.
808 } 813 }
809 814
810 815
811 } // namespace dart 816 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_optimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698