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

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

Issue 10914314: Simple redundant load elimination. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments 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_optimizer.h ('k') | runtime/vm/intermediate_language.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_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/cha.h" 8 #include "vm/cha.h"
9 #include "vm/flow_graph_builder.h" 9 #include "vm/flow_graph_builder.h"
10 #include "vm/hash_map.h" 10 #include "vm/hash_map.h"
11 #include "vm/il_printer.h" 11 #include "vm/il_printer.h"
12 #include "vm/object_store.h" 12 #include "vm/object_store.h"
13 #include "vm/parser.h" 13 #include "vm/parser.h"
14 #include "vm/scopes.h" 14 #include "vm/scopes.h"
15 #include "vm/symbols.h" 15 #include "vm/symbols.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 DECLARE_FLAG(bool, eliminate_type_checks); 19 DECLARE_FLAG(bool, eliminate_type_checks);
20 DECLARE_FLAG(bool, enable_type_checks); 20 DECLARE_FLAG(bool, enable_type_checks);
21 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); 21 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
22 DECLARE_FLAG(bool, trace_type_check_elimination); 22 DECLARE_FLAG(bool, trace_type_check_elimination);
23 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); 23 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
24 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
24 25
25 void FlowGraphOptimizer::ApplyICData() { 26 void FlowGraphOptimizer::ApplyICData() {
26 VisitBlocks(); 27 VisitBlocks();
27 } 28 }
28 29
29 30
30 void FlowGraphOptimizer::OptimizeComputations() { 31 void FlowGraphOptimizer::OptimizeComputations() {
31 for (intptr_t i = 0; i < block_order_.length(); ++i) { 32 for (intptr_t i = 0; i < block_order_.length(); ++i) {
32 BlockEntryInstr* entry = block_order_[i]; 33 BlockEntryInstr* entry = block_order_[i];
33 entry->Accept(this); 34 entry->Accept(this);
(...skipping 1505 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 current->InputAt(0)->definition()->IsPhi()) { 1540 current->InputAt(0)->definition()->IsPhi()) {
1540 TryHoistCheckSmiThroughPhi(&it, header, pre_header, current); 1541 TryHoistCheckSmiThroughPhi(&it, header, pre_header, current);
1541 } 1542 }
1542 } 1543 }
1543 } 1544 }
1544 } 1545 }
1545 } 1546 }
1546 } 1547 }
1547 1548
1548 1549
1549 void DominatorBasedCSE::Optimize(BlockEntryInstr* graph_entry) { 1550 static intptr_t NumberLoadExpressions(FlowGraph* graph) {
1550 ASSERT(graph_entry->IsGraphEntry());
1551 DirectChainedHashMap<Definition*> map; 1551 DirectChainedHashMap<Definition*> map;
1552 OptimizeRecursive(graph_entry, &map); 1552 intptr_t expr_id = 0;
1553 for (BlockIterator it = graph->reverse_postorder_iterator();
1554 !it.Done();
1555 it.Advance()) {
1556 BlockEntryInstr* block = it.Current();
1557 for (ForwardInstructionIterator instr_it(block);
1558 !instr_it.Done();
1559 instr_it.Advance()) {
1560 Definition* defn = instr_it.Current()->AsDefinition();
1561 if ((defn == NULL) ||
1562 !defn->IsLoadField() ||
1563 !defn->AffectedBySideEffect()) {
1564 // TODO(fschneider): Extend to other load instructions.
1565 continue;
1566 }
1567 Definition* result = map.Lookup(defn);
1568 if (result == NULL) {
1569 map.Insert(defn);
1570 defn->set_expr_id(expr_id++);
1571 } else {
1572 defn->set_expr_id(result->expr_id());
1573 }
1574 }
1575 }
1576 return expr_id;
1577 }
1578
1579
1580 static void ComputeAvailableLoads(
1581 FlowGraph* graph,
1582 intptr_t max_expr_id,
1583 const GrowableArray<BitVector*>& avail_in) {
1584 // Initialize gen-, kill-, out-sets.
1585 intptr_t num_blocks = graph->preorder().length();
1586 GrowableArray<BitVector*> avail_out(num_blocks);
1587 GrowableArray<BitVector*> avail_gen(num_blocks);
1588 GrowableArray<BitVector*> avail_kill(num_blocks);
1589 for (intptr_t i = 0; i < num_blocks; i++) {
1590 avail_out.Add(new BitVector(max_expr_id));
1591 avail_gen.Add(new BitVector(max_expr_id));
1592 avail_kill.Add(new BitVector(max_expr_id));
1593 }
1594
1595 for (BlockIterator block_it = graph->reverse_postorder_iterator();
1596 !block_it.Done();
1597 block_it.Advance()) {
1598 BlockEntryInstr* block = block_it.Current();
1599 intptr_t preorder_number = block->preorder_number();
1600 for (BackwardInstructionIterator instr_it(block);
1601 !instr_it.Done();
1602 instr_it.Advance()) {
1603 Instruction* instr = instr_it.Current();
1604 if (instr->HasSideEffect()) {
1605 avail_kill[preorder_number]->SetAll();
1606 break;
1607 }
1608 Definition* defn = instr_it.Current()->AsDefinition();
1609 if ((defn == NULL) ||
1610 !defn->IsLoadField() ||
1611 !defn->AffectedBySideEffect()) {
1612 // TODO(fschneider): Extend to other load instructions.
1613 continue;
1614 }
1615 avail_gen[preorder_number]->Add(defn->expr_id());
1616 }
1617 avail_out[preorder_number]->CopyFrom(avail_gen[preorder_number]);
1618 }
1619
1620 BitVector* temp = new BitVector(avail_in[0]->length());
1621
1622 bool changed = true;
1623 while (changed) {
1624 changed = false;
1625
1626 for (BlockIterator block_it = graph->reverse_postorder_iterator();
1627 !block_it.Done();
1628 block_it.Advance()) {
1629 BlockEntryInstr* block = block_it.Current();
1630 BitVector* block_in = avail_in[block->preorder_number()];
1631 BitVector* block_out = avail_out[block->preorder_number()];
1632 BitVector* block_kill = avail_kill[block->preorder_number()];
1633 BitVector* block_gen = avail_gen[block->preorder_number()];
1634
1635 if (FLAG_trace_optimization) {
1636 OS::Print("B%"Pd"", block->block_id());
1637 block_in->Print();
1638 block_out->Print();
1639 OS::Print("\n");
1640 }
1641
1642 // Compute block_in as the intersection of all out(p) where p
1643 // is a predecessor of the current block.
1644 if (block->IsGraphEntry()) {
1645 temp->Clear();
1646 } else {
1647 temp->SetAll();
1648 ASSERT(block->PredecessorCount() > 0);
1649 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
1650 BlockEntryInstr* pred = block->PredecessorAt(i);
1651 BitVector* pred_out = avail_out[pred->preorder_number()];
1652 temp->Intersect(*pred_out);
1653 }
1654 }
1655 if (!temp->Equals(*block_in)) {
1656 block_in->CopyFrom(temp);
1657 if (block_out->KillAndAdd(block_kill, block_gen)) changed = true;
1658 }
1659 }
1660 }
1661 }
1662
1663
1664 static void OptimizeLoads(
1665 BlockEntryInstr* block,
1666 GrowableArray<Definition*>* definitions,
1667 const GrowableArray<BitVector*>& avail_in) {
1668 // TODO(fschneider): Factor out code shared with the existing CSE pass.
1669
1670 // Delete loads that are killed (not available) at the entry.
1671 intptr_t pre_num = block->preorder_number();
1672 ASSERT(avail_in[pre_num]->length() == definitions->length());
1673 for (intptr_t i = 0; i < avail_in[pre_num]->length(); i++) {
1674 if (!avail_in[pre_num]->Contains(i)) {
1675 (*definitions)[i] = NULL;
1676 }
1677 }
1678
1679 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1680 Instruction* instr = it.Current();
1681 if (instr->HasSideEffect()) {
1682 // Handle local side effects by clearing current definitions.
1683 for (intptr_t i = 0; i < definitions->length(); i++) {
1684 (*definitions)[i] = NULL;
1685 }
1686 continue;
1687 }
1688 Definition* defn = instr->AsDefinition();
1689 if ((defn == NULL) ||
1690 !defn->IsLoadField() ||
1691 !defn->AffectedBySideEffect()) {
1692 // Immutable loads are handled in normal CSE.
1693 // TODO(fschneider): Extend to other load instructions.
1694 continue;
1695 }
1696 Definition* result = (*definitions)[defn->expr_id()];
1697 if (result == NULL) {
1698 (*definitions)[defn->expr_id()] = defn;
1699 continue;
1700 }
1701
1702 // Replace current with lookup result.
1703 defn->ReplaceUsesWith(result);
1704 it.RemoveCurrentFromGraph();
1705 if (FLAG_trace_optimization) {
1706 OS::Print("Replacing load v%"Pd" with v%"Pd"\n",
1707 defn->ssa_temp_index(),
1708 result->ssa_temp_index());
1709 }
1710 }
1711
1712 // Process children in the dominator tree recursively.
1713 intptr_t num_children = block->dominated_blocks().length();
1714 for (intptr_t i = 0; i < num_children; ++i) {
1715 BlockEntryInstr* child = block->dominated_blocks()[i];
1716 if (i < num_children - 1) {
1717 GrowableArray<Definition*> child_defs(definitions->length());
1718 child_defs.AddArray(*definitions);
1719 OptimizeLoads(child, &child_defs, avail_in);
1720 } else {
1721 OptimizeLoads(child, definitions, avail_in);
1722 }
1723 }
1724 }
1725
1726
1727 void DominatorBasedCSE::Optimize(FlowGraph* graph) {
1728 if (FLAG_load_cse) {
1729 intptr_t max_expr_id = NumberLoadExpressions(graph);
1730 if (max_expr_id > 0) {
1731 intptr_t num_blocks = graph->preorder().length();
1732 GrowableArray<BitVector*> avail_in(num_blocks);
1733 for (intptr_t i = 0; i < num_blocks; i++) {
1734 avail_in.Add(new BitVector(max_expr_id));
1735 }
1736
1737 ComputeAvailableLoads(graph, max_expr_id, avail_in);
1738
1739 GrowableArray<Definition*> definitions(max_expr_id);
1740 for (intptr_t j = 0; j < max_expr_id ; j++) {
1741 definitions.Add(NULL);
1742 }
1743
1744 OptimizeLoads(graph->graph_entry(), &definitions, avail_in);
1745 }
1746 }
1747
1748 DirectChainedHashMap<Definition*> map;
1749 OptimizeRecursive(graph->graph_entry(), &map);
1553 } 1750 }
1554 1751
1555 1752
1556 void DominatorBasedCSE::OptimizeRecursive( 1753 void DominatorBasedCSE::OptimizeRecursive(
1557 BlockEntryInstr* block, 1754 BlockEntryInstr* block,
1558 DirectChainedHashMap<Definition*>* map) { 1755 DirectChainedHashMap<Definition*>* map) {
1559 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 1756 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1560 Definition* defn = it.Current()->AsDefinition(); 1757 Definition* defn = it.Current()->AsDefinition();
1561 if ((defn == NULL) || defn->AffectedBySideEffect()) continue; 1758 if ((defn == NULL) || defn->AffectedBySideEffect()) continue;
1562 Definition* result = map->Lookup(defn); 1759 Definition* result = map->Lookup(defn);
(...skipping 19 matching lines...) Expand all
1582 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. 1779 DirectChainedHashMap<Definition*> child_map(*map); // Copy map.
1583 OptimizeRecursive(child, &child_map); 1780 OptimizeRecursive(child, &child_map);
1584 } else { 1781 } else {
1585 OptimizeRecursive(child, map); // Reuse map for the last child. 1782 OptimizeRecursive(child, map); // Reuse map for the last child.
1586 } 1783 }
1587 } 1784 }
1588 } 1785 }
1589 1786
1590 1787
1591 } // namespace dart 1788 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698