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

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

Issue 10943007: 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
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_.TruncateTo(0); 37 preorder_.Clear();
38 postorder_.TruncateTo(0); 38 postorder_.Clear();
39 reverse_postorder_.TruncateTo(0); 39 reverse_postorder_.Clear();
40 parent_.TruncateTo(0); 40 parent_.Clear();
41 assigned_vars_.TruncateTo(0); 41 assigned_vars_.Clear();
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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
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(&preorder_, &parent_, &dominance_frontier); 302 ComputeDominators(&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 //
325 // dominance_frontier: an output parameter encoding the dominance frontier. 317 // dominance_frontier: an output parameter encoding the dominance frontier.
326 // The array maps the preorder block number of a block to the set of 318 // The array maps the preorder block number of a block to the set of
327 // (preorder block numbers of) blocks in the dominance frontier. 319 // (preorder block numbers of) blocks in the dominance frontier.
328 void FlowGraph::ComputeDominators( 320 void FlowGraph::ComputeDominators(
329 GrowableArray<BlockEntryInstr*>* preorder,
330 GrowableArray<intptr_t>* parent,
331 GrowableArray<BitVector*>* dominance_frontier) { 321 GrowableArray<BitVector*>* dominance_frontier) {
332 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass 322 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
333 // version of the Lengauer-Tarjan algorithm (LT is normally three passes) 323 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
334 // that eliminates a pass by using nearest-common ancestor (NCA) to 324 // that eliminates a pass by using nearest-common ancestor (NCA) to
335 // compute immediate dominators from semidominators. It also removes a 325 // compute immediate dominators from semidominators. It also removes a
336 // level of indirection in the link-eval forest data structure. 326 // level of indirection in the link-eval forest data structure.
337 // 327 //
338 // The algorithm is described in Georgiadis, Tarjan, and Werneck's 328 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
339 // "Finding Dominators in Practice". 329 // "Finding Dominators in Practice".
340 // See http://www.cs.princeton.edu/~rwerneck/dominators/ . 330 // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
341 331
342 // All arrays are maps between preorder basic-block numbers. 332 // All arrays are maps between preorder basic-block numbers.
343 intptr_t size = parent->length(); 333 intptr_t size = parent_.length();
344 GrowableArray<intptr_t> idom(size); // Immediate dominator. 334 GrowableArray<intptr_t> idom(size); // Immediate dominator.
345 GrowableArray<intptr_t> semi(size); // Semidominator. 335 GrowableArray<intptr_t> semi(size); // Semidominator.
346 GrowableArray<intptr_t> label(size); // Label for link-eval forest. 336 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
347 337
348 // 1. First pass: compute semidominators as in Lengauer-Tarjan. 338 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
349 // Semidominators are computed from a depth-first spanning tree and are an 339 // Semidominators are computed from a depth-first spanning tree and are an
350 // approximation of immediate dominators. 340 // approximation of immediate dominators.
351 341
352 // Use a link-eval data structure with path compression. Implement path 342 // Use a link-eval data structure with path compression. Implement path
353 // compression in place by mutating the parent array. Each block has a 343 // compression in place by mutating the parent array. Each block has a
354 // label, which is the minimum block number on the compressed path. 344 // label, which is the minimum block number on the compressed path.
355 345
356 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the 346 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
357 // dominance frontier output array. 347 // dominance frontier output array.
358 for (intptr_t i = 0; i < size; ++i) { 348 for (intptr_t i = 0; i < size; ++i) {
359 idom.Add((*parent)[i]); 349 idom.Add(parent_[i]);
360 semi.Add(i); 350 semi.Add(i);
361 label.Add(i); 351 label.Add(i);
362 dominance_frontier->Add(new BitVector(size)); 352 dominance_frontier->Add(new BitVector(size));
363 } 353 }
364 354
365 // Loop over the blocks in reverse preorder (not including the graph 355 // Loop over the blocks in reverse preorder (not including the graph
366 // entry). 356 // entry).
367 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) { 357 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
368 // Loop over the predecessors. 358 // Loop over the predecessors.
369 BlockEntryInstr* block = (*preorder)[block_index]; 359 BlockEntryInstr* block = preorder_[block_index];
360 // Clear the immediately dominated blocks in case ComputeDominators is
361 // used to recompute them.
362 block->ClearDominatedBlocks();
370 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) { 363 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
371 BlockEntryInstr* pred = block->PredecessorAt(i); 364 BlockEntryInstr* pred = block->PredecessorAt(i);
372 ASSERT(pred != NULL); 365 ASSERT(pred != NULL);
373 366
374 // Look for the semidominator by ascending the semidominator path 367 // Look for the semidominator by ascending the semidominator path
375 // starting from pred. 368 // starting from pred.
376 intptr_t pred_index = pred->preorder_number(); 369 intptr_t pred_index = pred->preorder_number();
377 intptr_t best = pred_index; 370 intptr_t best = pred_index;
378 if (pred_index > block_index) { 371 if (pred_index > block_index) {
379 CompressPath(block_index, pred_index, parent, &label); 372 CompressPath(block_index, pred_index, &parent_, &label);
380 best = label[pred_index]; 373 best = label[pred_index];
381 } 374 }
382 375
383 // Update the semidominator if we've found a better one. 376 // Update the semidominator if we've found a better one.
384 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]); 377 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
385 } 378 }
386 379
387 // Now use label for the semidominator. 380 // Now use label for the semidominator.
388 label[block_index] = semi[block_index]; 381 label[block_index] = semi[block_index];
389 } 382 }
390 383
391 // 2. Compute the immediate dominators as the nearest common ancestor of 384 // 2. Compute the immediate dominators as the nearest common ancestor of
392 // spanning tree parent and semidominator, for all blocks except the entry. 385 // spanning tree parent and semidominator, for all blocks except the entry.
393 for (intptr_t block_index = 1; block_index < size; ++block_index) { 386 for (intptr_t block_index = 1; block_index < size; ++block_index) {
394 intptr_t dom_index = idom[block_index]; 387 intptr_t dom_index = idom[block_index];
395 while (dom_index > semi[block_index]) { 388 while (dom_index > semi[block_index]) {
396 dom_index = idom[dom_index]; 389 dom_index = idom[dom_index];
397 } 390 }
398 idom[block_index] = dom_index; 391 idom[block_index] = dom_index;
399 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]); 392 preorder_[block_index]->set_dominator(preorder_[dom_index]);
400 (*preorder)[dom_index]->AddDominatedBlock((*preorder)[block_index]); 393 preorder_[dom_index]->AddDominatedBlock(preorder_[block_index]);
401 } 394 }
402 395
403 // 3. Now compute the dominance frontier for all blocks. This is 396 // 3. Now compute the dominance frontier for all blocks. This is
404 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is 397 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is
405 // attributed to a paper by Ferrante et al. There is no bookkeeping 398 // attributed to a paper by Ferrante et al. There is no bookkeeping
406 // required to avoid adding a block twice to the same block's dominance 399 // required to avoid adding a block twice to the same block's dominance
407 // frontier because we use a set to represent the dominance frontier. 400 // frontier because we use a set to represent the dominance frontier.
408 for (intptr_t block_index = 0; block_index < size; ++block_index) { 401 for (intptr_t block_index = 0; block_index < size; ++block_index) {
409 BlockEntryInstr* block = (*preorder)[block_index]; 402 BlockEntryInstr* block = preorder_[block_index];
410 intptr_t count = block->PredecessorCount(); 403 intptr_t count = block->PredecessorCount();
411 if (count <= 1) continue; 404 if (count <= 1) continue;
412 for (intptr_t i = 0; i < count; ++i) { 405 for (intptr_t i = 0; i < count; ++i) {
413 BlockEntryInstr* runner = block->PredecessorAt(i); 406 BlockEntryInstr* runner = block->PredecessorAt(i);
414 while (runner != block->dominator()) { 407 while (runner != block->dominator()) {
415 (*dominance_frontier)[runner->preorder_number()]->Add(block_index); 408 (*dominance_frontier)[runner->preorder_number()]->Add(block_index);
416 runner = runner->dominator(); 409 runner = runner->dominator();
417 } 410 }
418 } 411 }
419 } 412 }
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 // TODO(zerny): Support multiple exits. 788 // TODO(zerny): Support multiple exits.
796 UNREACHABLE(); 789 UNREACHABLE();
797 } 790 }
798 791
799 // TODO(zerny): Adjust pre/post orders. 792 // TODO(zerny): Adjust pre/post orders.
800 // TODO(zerny): Update dominator tree. 793 // TODO(zerny): Update dominator tree.
801 } 794 }
802 795
803 796
804 } // namespace dart 797 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698