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

Unified Diff: runtime/vm/flow_graph_builder.cc

Issue 9729015: Compute immediate dominators using SEMI-NCA. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 9 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/flow_graph_builder.cc
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index d7b5139987dd4c3296d4e369950cf8128a708585..2867208c2886d8282285c1eb8864984dac0e78bf 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1671,11 +1671,12 @@ void FlowGraphBuilder::BuildGraph() {
if (for_effect.entry() != NULL) {
// Perform a depth-first traversal of the graph to build preorder and
// postorder block orders.
- GrowableArray<BlockEntryInstr*> parent;
+ GrowableArray<intptr_t> parent;
for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor.
&preorder_block_entries_,
&postorder_block_entries_,
&parent);
+ ComputeDominators(&preorder_block_entries_, &parent);
}
if (FLAG_print_flow_graph) {
intptr_t length = postorder_block_entries_.length();
@@ -1689,6 +1690,93 @@ void FlowGraphBuilder::BuildGraph() {
}
+void FlowGraphBuilder::ComputeDominators(
+ GrowableArray<BlockEntryInstr*>* preorder,
+ GrowableArray<intptr_t>* parent) {
+ // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
+ // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
+ // that eliminates a pass by using nearest-common ancestor (NCA) to
+ // compute immediate dominators from semidominators. It also removes a
+ // level of indirection in the link-eval forest data structure.
+ //
+ // The algorithm is described in Georgiadis, Tarjan, and Werneck's
+ // "Finding Dominators in Practice".
+ // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
+
+ // All arrays are indexed by preorder basic-block number.
+ intptr_t size = parent->length();
srdjan 2012/03/21 20:57:50 const intptr_t
+ GrowableArray<intptr_t> idom(size); // Immediate dominator.
+ GrowableArray<intptr_t> semi(size); // Semidominator index.
+ GrowableArray<intptr_t> label(size); // Label for link-eval forest.
+
+ // 1. First pass: compute semidominators as in Lengauer-Tarjan.
+ // Semidominators are computed from a depth-first spanning tree and are an
+ // approximation of immediate dominators.
+
+ // Use a link-eval data structure with path compression. Implement path
+ // compression in place by mutating the parent array. Each block has a
+ // label, which is the minimum block number on the compressed path.
+
+ // Initialize idom, semi, and label.
+ for (intptr_t i = 0; i < size; ++i) {
+ idom.Add((*parent)[i]);
+ semi.Add(i);
+ label.Add(i);
+ }
+
+ // Loop over the blocks in reverse preorder (not including the graph
+ // entry).
+ for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
+ // Loop over the predecessors.
+ BlockEntryInstr* block = (*preorder)[block_index];
+ for (intptr_t i = 0; i < block->PredecessorCount(); ++i) {
+ BlockEntryInstr* pred = block->PredecessorAt(i);
+ ASSERT(pred != NULL);
+
+ // Look for the semidominator by ascending the semidominator path
+ // starting from pred.
+ intptr_t pred_index = pred->preorder_number();
+ intptr_t best = pred_index;
+ if (pred_index > block_index) {
+ CompressPath(block_index, pred_index, parent, &label);
+ best = label[pred_index];
+ }
+
+ // Update the semidominator if we've found a better one.
+ semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
+ }
+
+ // Now use label for the semidominator.
+ label[block_index] = semi[block_index];
+ }
+
+ // 2. Compute the immediate dominators as the nearest common ancestor of
+ // spanning tree parent and semidominator, for all nodes except the entry.
+ for (intptr_t block_index = 1; block_index < size; ++block_index) {
+ intptr_t dom_index = idom[block_index];
+ while (dom_index > semi[block_index]) {
+ dom_index = idom[dom_index];
+ }
+ idom[block_index] = dom_index;
+ (*preorder)[block_index]->set_dominator((*preorder)[dom_index]);
+ }
+}
+
+
+void FlowGraphBuilder::CompressPath(intptr_t start_index,
+ intptr_t current_index,
+ GrowableArray<intptr_t>* parent,
+ GrowableArray<intptr_t>* label) {
+ intptr_t next_index = (*parent)[current_index];
+ if (next_index > start_index) {
+ CompressPath(start_index, next_index, parent, label);
+ (*label)[current_index] =
+ Utils::Minimum((*label)[current_index], (*label)[next_index]);
+ (*parent)[current_index] = (*parent)[next_index];
+ }
+}
+
+
void FlowGraphBuilder::Bailout(const char* reason) {
const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
const char* function_name = parsed_function_.function().ToCString();

Powered by Google App Engine
This is Rietveld 408576698