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

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: 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_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 Propagate(FlowGraph* graph,
Kevin Millikin (Google) 2012/09/17 12:09:47 Propagate is a generic name. How about "AnalyzeLo
Florian Schneider 2012/09/17 14:20:59 Done.
1581 const GrowableArray<BitVector*>& avail_in,
1582 const GrowableArray<BitVector*>& avail_out,
1583 const GrowableArray<BitVector*>& avail_gen,
1584 const GrowableArray<BitVector*>& avail_kill) {
1585 for (BlockIterator block_it = graph->reverse_postorder_iterator();
1586 !block_it.Done();
1587 block_it.Advance()) {
1588 BlockEntryInstr* block = block_it.Current();
1589 for (ForwardInstructionIterator instr_it(block);
Kevin Millikin (Google) 2012/09/17 12:09:47 If you iterate backward, you can break from the lo
Florian Schneider 2012/09/17 14:20:59 Done.
1590 !instr_it.Done();
1591 instr_it.Advance()) {
1592 Instruction* instr = instr_it.Current();
1593 if (instr->HasSideEffect()) {
1594 avail_gen[block->preorder_number()]->Clear();
1595 avail_out[block->preorder_number()]->Clear();
1596 avail_kill[block->preorder_number()]->SetAll();
1597 continue;
1598 }
1599 Definition* defn = instr_it.Current()->AsDefinition();
1600 if ((defn == NULL) ||
1601 !defn->IsLoadField() ||
1602 !defn->AffectedBySideEffect()) {
1603 // TODO(fschneider): Extend to other load instructions.
1604 continue;
1605 }
1606 avail_gen[block->preorder_number()]->Add(defn->expr_id());
Kevin Millikin (Google) 2012/09/17 12:09:47 It might be more straightforward to compute kill a
Florian Schneider 2012/09/17 14:20:59 Done.
1607 avail_out[block->preorder_number()]->Add(defn->expr_id());
1608 }
1609 }
1610
1611 BitVector* temp = new BitVector(avail_in[0]->length());
1612
1613 bool changed = true;
1614 while (changed) {
1615 changed = false;
1616
1617 for (BlockIterator block_it = graph->reverse_postorder_iterator();
1618 !block_it.Done();
1619 block_it.Advance()) {
1620 BlockEntryInstr* block = block_it.Current();
1621 BitVector* block_in = avail_in[block->preorder_number()];
1622 BitVector* block_out = avail_out[block->preorder_number()];
1623 BitVector* block_kill = avail_kill[block->preorder_number()];
1624 BitVector* block_gen = avail_gen[block->preorder_number()];
1625
1626 if (FLAG_trace_optimization) {
1627 OS::Print("B%"Pd"", block->block_id());
1628 block_in->Print();
1629 block_out->Print();
1630 OS::Print("\n");
1631 }
1632
1633 // Compute block_in as the intersection of all out(p) where p
1634 // is a predecessor of the current block.
1635 temp->Clear();
1636 for (intptr_t i = 0; i < block->PredecessorCount(); i++) {
1637 if (i == 0) temp->SetAll();
Kevin Millikin (Google) 2012/09/17 12:09:47 I prefer: if (block->IsGraphEntry()) { temp->Cl
Florian Schneider 2012/09/17 14:20:59 Done.
1638 BlockEntryInstr* pred = block->PredecessorAt(i);
1639 BitVector* pred_out = avail_out[pred->preorder_number()];
1640 temp->Intersect(*pred_out);
1641 }
1642 if (!temp->Equals(*block_in)) {
1643 block_in->Clear();
Kevin Millikin (Google) 2012/09/17 12:09:47 Seems like we might as well combine Clear and AddA
Florian Schneider 2012/09/17 14:20:59 Done.
1644 block_in->AddAll(temp);
1645 if (block_out->KillAndAdd(block_kill, block_gen)) changed = true;
1646 }
1647 }
1648 }
1649 }
1650
1651
1652 static void OptimizeLoads(
1653 BlockEntryInstr* block,
1654 GrowableArray<Definition*>* definitions,
1655 const GrowableArray<BitVector*>& avail_in) {
1656 // TODO(fschneider): Factor out code shared with the existing CSE pass.
1657
1658 // Delete loads that are killed (not available) at the entry.
1659 intptr_t pre_num = block->preorder_number();
1660 ASSERT(avail_in[pre_num]->length() == definitions->length());
1661 for (intptr_t i = 0; i < avail_in[pre_num]->length(); i++) {
1662 if (!avail_in[pre_num]->Contains(i)) {
1663 (*definitions)[i] = NULL;
1664 }
1665 }
1666
1667 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1668 Instruction* instr = it.Current();
1669 if (instr->HasSideEffect()) {
1670 // Handle local side effects by clearing current definitions.
1671 for (intptr_t i = 0; i < definitions->length(); i++) {
1672 (*definitions)[i] = NULL;
1673 }
1674 continue;
1675 }
1676 Definition* defn = instr->AsDefinition();
1677 if ((defn == NULL) ||
1678 !defn->IsLoadField() ||
1679 !defn->AffectedBySideEffect()) {
1680 // Immutable loads are handled in normal CSE.
1681 // TODO(fschneider): Extend to other load instructions.
1682 continue;
1683 }
1684 Definition* result = (*definitions)[defn->expr_id()];
1685 if (result == NULL) {
1686 (*definitions)[defn->expr_id()] = defn;
1687 continue;
1688 }
1689
1690 // Replace current with lookup result.
1691 defn->ReplaceUsesWith(result);
1692 it.RemoveCurrentFromGraph();
1693 if (FLAG_trace_optimization) {
1694 OS::Print("Replacing load v%"Pd" with v%"Pd"\n",
1695 defn->ssa_temp_index(),
1696 result->ssa_temp_index());
1697 }
1698 }
1699
1700 // Process children in the dominator tree recursively.
1701 intptr_t num_children = block->dominated_blocks().length();
1702 for (intptr_t i = 0; i < num_children; ++i) {
1703 BlockEntryInstr* child = block->dominated_blocks()[i];
1704 if (i < num_children - 1) {
1705 GrowableArray<Definition*> child_defs(definitions->length());
1706 child_defs.AddArray(*definitions);
1707 OptimizeLoads(child, &child_defs, avail_in);
1708 } else {
1709 OptimizeLoads(child, definitions, avail_in);
1710 }
1711 }
1712 }
1713
1714
1715 void DominatorBasedCSE::Optimize(FlowGraph* graph) {
1716 intptr_t max_expr_id = NumberLoadExpressions(graph);
Kevin Millikin (Google) 2012/09/17 12:09:47 Can we move NumberLoadExpressions(graph) inside an
Florian Schneider 2012/09/17 14:20:59 Done.
1717 if (max_expr_id > 0 && FLAG_load_cse) {
1718 intptr_t num_blocks = graph->preorder().length();
1719 GrowableArray<BitVector*> avail_out(num_blocks);
Kevin Millikin (Google) 2012/09/17 12:09:47 I'd move avail_gen, and _kill into Propagate so it
Florian Schneider 2012/09/17 14:20:59 Done.
1720 GrowableArray<BitVector*> avail_in(num_blocks);
1721 GrowableArray<BitVector*> avail_gen(num_blocks);
1722 GrowableArray<BitVector*> avail_kill(num_blocks);
1723 for (intptr_t i = 0; i < num_blocks; i++) {
1724 avail_out.Add(new BitVector(max_expr_id));
1725 avail_in.Add(new BitVector(max_expr_id));
1726 avail_gen.Add(new BitVector(max_expr_id));
1727 avail_kill.Add(new BitVector(max_expr_id));
1728 }
1729
1730 Propagate(graph, avail_in, avail_out, avail_gen, avail_kill);
1731
1732 GrowableArray<Definition*> definitions(max_expr_id);
1733 for (intptr_t j = 0; j < max_expr_id ; j++) {
1734 definitions.Add(NULL);
1735 }
1736
1737 OptimizeLoads(graph->graph_entry(), &definitions, avail_in);
1738 }
1739
1740 DirectChainedHashMap<Definition*> map;
1741 OptimizeRecursive(graph->graph_entry(), &map);
1553 } 1742 }
1554 1743
1555 1744
1556 void DominatorBasedCSE::OptimizeRecursive( 1745 void DominatorBasedCSE::OptimizeRecursive(
1557 BlockEntryInstr* block, 1746 BlockEntryInstr* block,
1558 DirectChainedHashMap<Definition*>* map) { 1747 DirectChainedHashMap<Definition*>* map) {
1559 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 1748 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1560 Definition* defn = it.Current()->AsDefinition(); 1749 Definition* defn = it.Current()->AsDefinition();
1561 if ((defn == NULL) || defn->AffectedBySideEffect()) continue; 1750 if ((defn == NULL) || defn->AffectedBySideEffect()) continue;
1562 Definition* result = map->Lookup(defn); 1751 Definition* result = map->Lookup(defn);
(...skipping 19 matching lines...) Expand all
1582 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. 1771 DirectChainedHashMap<Definition*> child_map(*map); // Copy map.
1583 OptimizeRecursive(child, &child_map); 1772 OptimizeRecursive(child, &child_map);
1584 } else { 1773 } else {
1585 OptimizeRecursive(child, map); // Reuse map for the last child. 1774 OptimizeRecursive(child, map); // Reuse map for the last child.
1586 } 1775 }
1587 } 1776 }
1588 } 1777 }
1589 1778
1590 1779
1591 } // namespace dart 1780 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698