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

Side by Side 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 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_builder.h" 5 #include "vm/flow_graph_builder.h"
6 6
7 #include "vm/ast_printer.h" 7 #include "vm/ast_printer.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/intermediate_language.h" 9 #include "vm/intermediate_language.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 1653 matching lines...) Expand 10 before | Expand all | Expand 10 after
1664 } 1664 }
1665 const Function& function = parsed_function().function(); 1665 const Function& function = parsed_function().function();
1666 EffectGraphVisitor for_effect(this, 0); 1666 EffectGraphVisitor for_effect(this, 0);
1667 for_effect.AddInstruction(new TargetEntryInstr()); 1667 for_effect.AddInstruction(new TargetEntryInstr());
1668 parsed_function().node_sequence()->Visit(&for_effect); 1668 parsed_function().node_sequence()->Visit(&for_effect);
1669 // Check that the graph is properly terminated. 1669 // Check that the graph is properly terminated.
1670 ASSERT(!for_effect.is_open()); 1670 ASSERT(!for_effect.is_open());
1671 if (for_effect.entry() != NULL) { 1671 if (for_effect.entry() != NULL) {
1672 // Perform a depth-first traversal of the graph to build preorder and 1672 // Perform a depth-first traversal of the graph to build preorder and
1673 // postorder block orders. 1673 // postorder block orders.
1674 GrowableArray<BlockEntryInstr*> parent; 1674 GrowableArray<intptr_t> parent;
1675 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor. 1675 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor.
1676 &preorder_block_entries_, 1676 &preorder_block_entries_,
1677 &postorder_block_entries_, 1677 &postorder_block_entries_,
1678 &parent); 1678 &parent);
1679 ComputeDominators(&preorder_block_entries_, &parent);
1679 } 1680 }
1680 if (FLAG_print_flow_graph) { 1681 if (FLAG_print_flow_graph) {
1681 intptr_t length = postorder_block_entries_.length(); 1682 intptr_t length = postorder_block_entries_.length();
1682 GrowableArray<BlockEntryInstr*> reverse_postorder(length); 1683 GrowableArray<BlockEntryInstr*> reverse_postorder(length);
1683 for (intptr_t i = length - 1; i >= 0; --i) { 1684 for (intptr_t i = length - 1; i >= 0; --i) {
1684 reverse_postorder.Add(postorder_block_entries_[i]); 1685 reverse_postorder.Add(postorder_block_entries_[i]);
1685 } 1686 }
1686 FlowGraphPrinter printer(function, reverse_postorder); 1687 FlowGraphPrinter printer(function, reverse_postorder);
1687 printer.VisitBlocks(); 1688 printer.VisitBlocks();
1688 } 1689 }
1689 } 1690 }
1690 1691
1691 1692
1693 void FlowGraphBuilder::ComputeDominators(
1694 GrowableArray<BlockEntryInstr*>* preorder,
1695 GrowableArray<intptr_t>* parent) {
1696 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
1697 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
1698 // that eliminates a pass by using nearest-common ancestor (NCA) to
1699 // compute immediate dominators from semidominators. It also removes a
1700 // level of indirection in the link-eval forest data structure.
1701 //
1702 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
1703 // "Finding Dominators in Practice".
1704 // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
1705
1706 // All arrays are indexed by preorder basic-block number.
1707 intptr_t size = parent->length();
srdjan 2012/03/21 20:57:50 const intptr_t
1708 GrowableArray<intptr_t> idom(size); // Immediate dominator.
1709 GrowableArray<intptr_t> semi(size); // Semidominator index.
1710 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
1711
1712 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
1713 // Semidominators are computed from a depth-first spanning tree and are an
1714 // approximation of immediate dominators.
1715
1716 // Use a link-eval data structure with path compression. Implement path
1717 // compression in place by mutating the parent array. Each block has a
1718 // label, which is the minimum block number on the compressed path.
1719
1720 // Initialize idom, semi, and label.
1721 for (intptr_t i = 0; i < size; ++i) {
1722 idom.Add((*parent)[i]);
1723 semi.Add(i);
1724 label.Add(i);
1725 }
1726
1727 // Loop over the blocks in reverse preorder (not including the graph
1728 // entry).
1729 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
1730 // Loop over the predecessors.
1731 BlockEntryInstr* block = (*preorder)[block_index];
1732 for (intptr_t i = 0; i < block->PredecessorCount(); ++i) {
1733 BlockEntryInstr* pred = block->PredecessorAt(i);
1734 ASSERT(pred != NULL);
1735
1736 // Look for the semidominator by ascending the semidominator path
1737 // starting from pred.
1738 intptr_t pred_index = pred->preorder_number();
1739 intptr_t best = pred_index;
1740 if (pred_index > block_index) {
1741 CompressPath(block_index, pred_index, parent, &label);
1742 best = label[pred_index];
1743 }
1744
1745 // Update the semidominator if we've found a better one.
1746 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
1747 }
1748
1749 // Now use label for the semidominator.
1750 label[block_index] = semi[block_index];
1751 }
1752
1753 // 2. Compute the immediate dominators as the nearest common ancestor of
1754 // spanning tree parent and semidominator, for all nodes except the entry.
1755 for (intptr_t block_index = 1; block_index < size; ++block_index) {
1756 intptr_t dom_index = idom[block_index];
1757 while (dom_index > semi[block_index]) {
1758 dom_index = idom[dom_index];
1759 }
1760 idom[block_index] = dom_index;
1761 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]);
1762 }
1763 }
1764
1765
1766 void FlowGraphBuilder::CompressPath(intptr_t start_index,
1767 intptr_t current_index,
1768 GrowableArray<intptr_t>* parent,
1769 GrowableArray<intptr_t>* label) {
1770 intptr_t next_index = (*parent)[current_index];
1771 if (next_index > start_index) {
1772 CompressPath(start_index, next_index, parent, label);
1773 (*label)[current_index] =
1774 Utils::Minimum((*label)[current_index], (*label)[next_index]);
1775 (*parent)[current_index] = (*parent)[next_index];
1776 }
1777 }
1778
1779
1692 void FlowGraphBuilder::Bailout(const char* reason) { 1780 void FlowGraphBuilder::Bailout(const char* reason) {
1693 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; 1781 const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
1694 const char* function_name = parsed_function_.function().ToCString(); 1782 const char* function_name = parsed_function_.function().ToCString();
1695 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 1783 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
1696 char* chars = reinterpret_cast<char*>( 1784 char* chars = reinterpret_cast<char*>(
1697 Isolate::Current()->current_zone()->Allocate(len)); 1785 Isolate::Current()->current_zone()->Allocate(len));
1698 OS::SNPrint(chars, len, kFormat, function_name, reason); 1786 OS::SNPrint(chars, len, kFormat, function_name, reason);
1699 const Error& error = Error::Handle( 1787 const Error& error = Error::Handle(
1700 LanguageError::New(String::Handle(String::New(chars)))); 1788 LanguageError::New(String::Handle(String::New(chars))));
1701 Isolate::Current()->long_jump_base()->Jump(1, error); 1789 Isolate::Current()->long_jump_base()->Jump(1, error);
1702 } 1790 }
1703 1791
1704 1792
1705 } // namespace dart 1793 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698