| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |