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

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

Issue 10972003: Fix convergence issues in range analysis. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: address 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/compiler.cc ('k') | runtime/vm/il_printer.cc » ('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/intermediate_language.h" 12 #include "vm/intermediate_language.h"
13 #include "vm/object_store.h" 13 #include "vm/object_store.h"
14 #include "vm/parser.h" 14 #include "vm/parser.h"
15 #include "vm/scopes.h" 15 #include "vm/scopes.h"
16 #include "vm/symbols.h" 16 #include "vm/symbols.h"
17 17
18 namespace dart { 18 namespace dart {
19 19
20 DECLARE_FLAG(bool, eliminate_type_checks); 20 DECLARE_FLAG(bool, eliminate_type_checks);
21 DECLARE_FLAG(bool, enable_type_checks); 21 DECLARE_FLAG(bool, enable_type_checks);
22 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); 22 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
23 DECLARE_FLAG(bool, trace_type_check_elimination); 23 DECLARE_FLAG(bool, trace_type_check_elimination);
24 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis."); 24 DEFINE_FLAG(bool, use_cha, true, "Use class hierarchy analysis.");
25 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); 25 DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination.");
26 DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress");
26 27
27 void FlowGraphOptimizer::ApplyICData() { 28 void FlowGraphOptimizer::ApplyICData() {
28 VisitBlocks(); 29 VisitBlocks();
29 } 30 }
30 31
31 32
32 static void ReplaceCurrentInstruction(ForwardInstructionIterator* it, 33 static void ReplaceCurrentInstruction(ForwardInstructionIterator* it,
33 Instruction* current, 34 Instruction* current,
34 Instruction* replacement) { 35 Instruction* replacement) {
35 if ((replacement != NULL) && current->IsDefinition()) { 36 if ((replacement != NULL) && current->IsDefinition()) {
(...skipping 1196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1232 1233
1233 // Replace uses of the definition def that are dominated by instruction dom 1234 // Replace uses of the definition def that are dominated by instruction dom
1234 // with uses of other definition. 1235 // with uses of other definition.
1235 void RenameDominatedUses(Definition* def, 1236 void RenameDominatedUses(Definition* def,
1236 Instruction* dom, 1237 Instruction* dom,
1237 Definition* other); 1238 Definition* other);
1238 1239
1239 // Propagate range information until fix-point is reached. 1240 // Propagate range information until fix-point is reached.
1240 void InferRanges(); 1241 void InferRanges();
1241 1242
1243 void ProcessWorklist(Definition::RangeOperator op);
1244
1242 // Walk the dominator tree, initialize ranges for smi values and place them 1245 // Walk the dominator tree, initialize ranges for smi values and place them
1243 // to the worklist. 1246 // to the worklist.
1244 void InitializeRangesRecursive(BlockEntryInstr* block); 1247 void InitializeRangesRecursive(BlockEntryInstr* block);
1245 1248
1246 // Remove artificial Constraint instructions and replace them with actual 1249 // Remove artificial Constraint instructions and replace them with actual
1247 // unconstrained definitions. 1250 // unconstrained definitions.
1248 void RemoveConstraints(); 1251 void RemoveConstraints();
1249 1252
1250 void CreateWorklists(); 1253 void CreateWorklists();
1251 1254
1252 void AddToWorklist(Definition* value) { 1255 void AddToWorklist(Definition* value) {
1253 const intptr_t index = value->ssa_temp_index(); 1256 const intptr_t index = value->ssa_temp_index();
1254 if (!in_inactive_worklist_->Contains(index)) { 1257 if (!in_worklist_->Contains(index)) {
1255 in_inactive_worklist_->Add(index); 1258 in_worklist_->Add(index);
1256 inactive_worklist_->Add(value); 1259 worklist_.Add(value);
1257 } 1260 }
1258 } 1261 }
1259 1262
1260 bool IsWorklistEmpty() const { 1263 bool IsWorklistEmpty() const {
1261 return active_worklist_->is_empty(); 1264 return worklist_.is_empty();
1265 }
1266
1267 Definition* RemoveLastFromWorklist() {
1268 Definition* defn = worklist_.Last();
1269 worklist_.RemoveLast();
1270 ASSERT(in_worklist_->Contains(defn->ssa_temp_index()));
1271 in_worklist_->Remove(defn->ssa_temp_index());
1272 return defn;
1262 } 1273 }
1263 1274
1264 void SwapWorklists(); 1275 void SwapWorklists();
1265 1276
1266 FlowGraph* flow_graph_; 1277 FlowGraph* flow_graph_;
1267 1278
1268 GrowableArray<Definition*> smi_values_; // Value that are known to be smi. 1279 GrowableArray<Definition*> smi_values_; // Value that are known to be smi.
1269 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions. 1280 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions.
1270 1281
1271 // All Constraints inserted during InsertConstraints phase. They are treated 1282 // All Constraints inserted during InsertConstraints phase. They are treated
1272 // as smi values. 1283 // as smi values.
1273 GrowableArray<ConstraintInstr*> constraints_; 1284 GrowableArray<ConstraintInstr*> constraints_;
1274 1285
1275 // Bitvector for a quick filtering of known smi values. 1286 // Bitvector for a quick filtering of known smi values.
1276 BitVector* smi_definitions_; 1287 BitVector* smi_definitions_;
1277 1288
1278 // Worklists using during range propagation. 1289 // Worklist used during range propagation.
1279 ZoneGrowableArray<Definition*>* active_worklist_; 1290 GrowableArray<Definition*> worklist_;
1280 ZoneGrowableArray<Definition*>* inactive_worklist_; 1291 BitVector* in_worklist_;
1281 BitVector* in_inactive_worklist_;
1282 1292
1283 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); 1293 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis);
1284 }; 1294 };
1285 1295
1286 1296
1287 void RangeAnalysis::Analyze() { 1297 void RangeAnalysis::Analyze() {
1288 CollectSmiValues(); 1298 CollectSmiValues();
1289 InsertConstraints(); 1299 InsertConstraints();
1290 InferRanges(); 1300 InferRanges();
1291 RemoveConstraints(); 1301 RemoveConstraints();
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 } 1536 }
1527 1537
1528 for (intptr_t i = 0; i < smi_values_.length(); i++) { 1538 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1529 InsertConstraintsFor(smi_values_[i]); 1539 InsertConstraintsFor(smi_values_[i]);
1530 } 1540 }
1531 } 1541 }
1532 1542
1533 1543
1534 void RangeAnalysis::InitializeRangesRecursive(BlockEntryInstr* block) { 1544 void RangeAnalysis::InitializeRangesRecursive(BlockEntryInstr* block) {
1535 JoinEntryInstr* join = block->AsJoinEntry(); 1545 JoinEntryInstr* join = block->AsJoinEntry();
1536 if ((join != NULL) && (join->phis() != NULL)) { 1546 if (join != NULL) {
1537 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 1547 for (PhiIterator it(join); !it.Done(); it.Advance()) {
1538 PhiInstr* phi = (*join->phis())[i]; 1548 PhiInstr* phi = it.Current();
1539 if (phi == NULL) continue;
1540 if (smi_definitions_->Contains(phi->ssa_temp_index())) { 1549 if (smi_definitions_->Contains(phi->ssa_temp_index())) {
1541 phi->InferRange(); 1550 phi->InferRange(Definition::kRangeInit);
1542 AddToWorklist(phi); 1551 AddToWorklist(phi);
1543 } 1552 }
1544 } 1553 }
1545 } 1554 }
1546 1555
1547 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 1556 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1548 Definition* defn = it.Current()->AsDefinition(); 1557 Definition* defn = it.Current()->AsDefinition();
1549 if ((defn != NULL) && 1558 if ((defn != NULL) &&
1550 (defn->ssa_temp_index() != -1) && 1559 (defn->ssa_temp_index() != -1) &&
1551 smi_definitions_->Contains(defn->ssa_temp_index())) { 1560 smi_definitions_->Contains(defn->ssa_temp_index())) {
1552 defn->InferRange(); 1561 defn->InferRange(Definition::kRangeInit);
1553 AddToWorklist(defn); 1562 AddToWorklist(defn);
1554 } 1563 }
1555 } 1564 }
1556 1565
1557 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { 1566 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) {
1558 InitializeRangesRecursive(block->dominated_blocks()[i]); 1567 InitializeRangesRecursive(block->dominated_blocks()[i]);
1559 } 1568 }
1560 } 1569 }
1561 1570
1562 1571
1563 void RangeAnalysis::CreateWorklists() { 1572 void RangeAnalysis::CreateWorklists() {
1564 active_worklist_ = new ZoneGrowableArray<Definition*>(10); 1573 in_worklist_ = new BitVector(flow_graph_->current_ssa_temp_index());
1565 inactive_worklist_ = new ZoneGrowableArray<Definition*>(10);
1566 in_inactive_worklist_ = new BitVector(
1567 flow_graph_->current_ssa_temp_index());
1568 } 1574 }
1569 1575
1570 1576
1571 void RangeAnalysis::SwapWorklists() { 1577 void RangeAnalysis::ProcessWorklist(Definition::RangeOperator op) {
1572 ZoneGrowableArray<Definition*>* temp = active_worklist_; 1578 // Iterate until fix point is reached.
1573 active_worklist_ = inactive_worklist_; 1579 while (!IsWorklistEmpty()) {
1574 inactive_worklist_ = temp; 1580 Definition* defn = RemoveLastFromWorklist();
1575 inactive_worklist_->Clear(); 1581 if (FLAG_trace_range_analysis) {
1576 in_inactive_worklist_->Clear(); 1582 OS::Print("infering range for v%"Pd" %s\n",
1583 defn->ssa_temp_index(),
1584 Range::ToCString(defn->range()));
1585 }
1586 if (defn->InferRange(op)) { // Update the range.
1587 if (FLAG_trace_range_analysis) {
1588 OS::Print(" changed to %s\n", Range::ToCString(defn->range()));
1589 }
1590 // Range change. Place all uses to the worklist.
1591 for (Value* use = defn->input_use_list();
1592 use != NULL;
1593 use = use->next_use()) {
1594 Definition* use_defn = use->instruction()->AsDefinition();
1595 if ((use_defn != NULL) &&
1596 (use_defn->ssa_temp_index() != -1) &&
1597 smi_definitions_->Contains(use_defn->ssa_temp_index())) {
1598 AddToWorklist(use_defn);
1599 }
1600 }
1601 }
1602 }
1577 } 1603 }
1578 1604
1579 1605
1580 void RangeAnalysis::InferRanges() { 1606 void RangeAnalysis::InferRanges() {
1581 CreateWorklists(); 1607 CreateWorklists();
1582 1608
1583 // Initialize bitvector for quick filtering of smi values. 1609 // Initialize bitvector for quick filtering of smi values.
1584 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index()); 1610 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index());
1585 for (intptr_t i = 0; i < smi_values_.length(); i++) { 1611 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1586 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); 1612 smi_definitions_->Add(smi_values_[i]->ssa_temp_index());
1587 } 1613 }
1588 for (intptr_t i = 0; i < constraints_.length(); i++) { 1614 for (intptr_t i = 0; i < constraints_.length(); i++) {
1589 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); 1615 smi_definitions_->Add(constraints_[i]->ssa_temp_index());
1590 } 1616 }
1591 1617
1592 // Infer initial values of ranges. 1618 // Infer initial values of ranges.
1593 InitializeRangesRecursive(flow_graph_->graph_entry()); 1619 InitializeRangesRecursive(flow_graph_->graph_entry());
1594 1620
1595 // Active worklist is empty, inactive now contains all smi values. 1621 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1596 SwapWorklists(); 1622 if (smi_values_[i]->IsPhi() &&
1597 1623 smi_values_[i]->InferRange(Definition::kRangeInit)) {
1598 // Iterate until fix point is reached. 1624 Definition* defn = smi_values_[i];
1599 while (!IsWorklistEmpty()) { 1625 for (Value* use = defn->input_use_list();
1600 for (intptr_t i = 0; i < active_worklist_->length(); i++) { 1626 use != NULL;
1601 Definition* defn = (*active_worklist_)[i]; 1627 use = use->next_use()) {
1602 if (defn->InferRange()) { // Update the range. 1628 Definition* use_defn = use->instruction()->AsDefinition();
1603 // Range change. Place all uses to the worklist. 1629 if ((use_defn != NULL) &&
1604 for (Value* use = defn->input_use_list(); 1630 (use_defn->ssa_temp_index() != -1) &&
1605 use != NULL; 1631 smi_definitions_->Contains(use_defn->ssa_temp_index())) {
1606 use = use->next_use()) { 1632 AddToWorklist(use_defn);
1607 Definition* use_defn = use->instruction()->AsDefinition();
1608 if ((use_defn != NULL) &&
1609 (use_defn->ssa_temp_index() != -1) &&
1610 smi_definitions_->Contains(use_defn->ssa_temp_index())) {
1611 AddToWorklist(use_defn);
1612 }
1613 } 1633 }
1614 } 1634 }
1615 } 1635 }
1636 }
1616 1637
1617 // Active worklist has been processed. Inactive contains all values which 1638 if (FLAG_trace_range_analysis) {
1618 // can be affected by changed ranges. 1639 OS::Print("---- after initialization -------\n");
1619 SwapWorklists(); 1640 FlowGraphPrinter printer(*flow_graph_);
1641 printer.PrintBlocks();
1642 }
1643
1644 if (FLAG_trace_range_analysis) {
1645 OS::Print("---- widening ---------\n");
1646 }
1647 ProcessWorklist(Definition::kRangeWiden);
1648
1649 if (FLAG_trace_range_analysis) {
1650 OS::Print("---- after widening -------\n");
1651 FlowGraphPrinter printer(*flow_graph_);
1652 printer.PrintBlocks();
1653 }
1654
1655 if (FLAG_trace_range_analysis) {
1656 OS::Print("---- narrowing ---------\n");
1657 }
1658 // Only phis can change under narrowing operator. Place all phis
1659 // into the worklist.
1660 for (intptr_t i = 0; i < smi_values_.length(); i++) {
1661 if (smi_values_[i]->IsPhi()) AddToWorklist(smi_values_[i]);
1662 }
1663 ProcessWorklist(Definition::kRangeNarrow);
1664
1665 if (FLAG_trace_range_analysis) {
1666 OS::Print("---- after narrowing -------\n");
1667 FlowGraphPrinter printer(*flow_graph_);
1668 printer.PrintBlocks();
1620 } 1669 }
1621 } 1670 }
1622 1671
1623 1672
1624 void RangeAnalysis::RemoveConstraints() { 1673 void RangeAnalysis::RemoveConstraints() {
1625 for (intptr_t i = 0; i < constraints_.length(); i++) { 1674 for (intptr_t i = 0; i < constraints_.length(); i++) {
1626 Definition* def = constraints_[i]->value()->definition(); 1675 Definition* def = constraints_[i]->value()->definition();
1627 // Some constraints might be constraining constraints. Unwind the chain of 1676 // Some constraints might be constraining constraints. Unwind the chain of
1628 // constraints until we reach the actual definition. 1677 // constraints until we reach the actual definition.
1629 while (def->IsConstraint()) { 1678 while (def->IsConstraint()) {
(...skipping 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after
2939 it.Advance()) { 2988 it.Advance()) {
2940 JoinEntryInstr* join = it.Current()->AsJoinEntry(); 2989 JoinEntryInstr* join = it.Current()->AsJoinEntry();
2941 if (join != NULL) join->EliminateUnreachablePhiInputs(); 2990 if (join != NULL) join->EliminateUnreachablePhiInputs();
2942 } 2991 }
2943 2992
2944 graph_->ComputeUseLists(); 2993 graph_->ComputeUseLists();
2945 } 2994 }
2946 2995
2947 2996
2948 } // namespace dart 2997 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/compiler.cc ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698