Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 1584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1595 | 1595 |
| 1596 void FlowGraphOptimizer::PropagateSminess() { | 1596 void FlowGraphOptimizer::PropagateSminess() { |
| 1597 SminessPropagator propagator(flow_graph_); | 1597 SminessPropagator propagator(flow_graph_); |
| 1598 propagator.Propagate(); | 1598 propagator.Propagate(); |
| 1599 } | 1599 } |
| 1600 | 1600 |
| 1601 | 1601 |
| 1602 // Range analysis for smi values. | 1602 // Range analysis for smi values. |
| 1603 class RangeAnalysis : public ValueObject { | 1603 class RangeAnalysis : public ValueObject { |
| 1604 public: | 1604 public: |
| 1605 explicit RangeAnalysis(FlowGraph* flow_graph) : flow_graph_(flow_graph) { } | 1605 explicit RangeAnalysis(FlowGraph* flow_graph) |
| 1606 : flow_graph_(flow_graph), | |
| 1607 marked_defns_(NULL) { } | |
| 1606 | 1608 |
| 1607 // Infer ranges for all values and remove overflow checks from binary smi | 1609 // Infer ranges for all values and remove overflow checks from binary smi |
| 1608 // operations when proven redundant. | 1610 // operations when proven redundant. |
| 1609 void Analyze(); | 1611 void Analyze(); |
| 1610 | 1612 |
| 1611 private: | 1613 private: |
| 1612 // Collect all values that were proven to be smi in smi_values_ array and all | 1614 // Collect all values that were proven to be smi in smi_values_ array and all |
| 1613 // CheckSmi instructions in smi_check_ array. | 1615 // CheckSmi instructions in smi_check_ array. |
| 1614 void CollectSmiValues(); | 1616 void CollectSmiValues(); |
| 1615 | 1617 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1628 ConstraintInstr* InsertConstraintFor(Definition* defn, | 1630 ConstraintInstr* InsertConstraintFor(Definition* defn, |
| 1629 Range* constraint, | 1631 Range* constraint, |
| 1630 Instruction* after); | 1632 Instruction* after); |
| 1631 | 1633 |
| 1632 // Replace uses of the definition def that are dominated by instruction dom | 1634 // Replace uses of the definition def that are dominated by instruction dom |
| 1633 // with uses of other definition. | 1635 // with uses of other definition. |
| 1634 void RenameDominatedUses(Definition* def, | 1636 void RenameDominatedUses(Definition* def, |
| 1635 Instruction* dom, | 1637 Instruction* dom, |
| 1636 Definition* other); | 1638 Definition* other); |
| 1637 | 1639 |
| 1638 // Propagate range information until fix-point is reached. | 1640 |
| 1641 // Walk the dominator tree and infer ranges for smi values. | |
| 1639 void InferRanges(); | 1642 void InferRanges(); |
| 1643 void InferRangesRecursive(BlockEntryInstr* block); | |
| 1640 | 1644 |
| 1641 void ProcessWorklist(Definition::RangeOperator op); | 1645 enum GrowthDirection { |
|
Florian Schneider
2012/10/25 11:15:43
I'd rename this to just Direction. Growth implies
Vyacheslav Egorov (Google)
2012/10/25 11:24:27
Done.
| |
| 1646 UNKNOWN, | |
|
Florian Schneider
2012/10/25 11:15:43
Maybe rename to the more common style
kUnknown, k
Vyacheslav Egorov (Google)
2012/10/25 11:24:27
Done.
| |
| 1647 POSITIVE, | |
| 1648 NEGATIVE, | |
| 1649 BOTH | |
| 1650 }; | |
| 1642 | 1651 |
| 1643 // Walk the dominator tree, initialize ranges for smi values and place them | 1652 Range* InferInductionVariableRange(JoinEntryInstr* loop_header, |
| 1644 // to the worklist. | 1653 PhiInstr* var); |
| 1645 void InitializeRangesRecursive(BlockEntryInstr* block); | 1654 |
| 1655 void ResetWorklist(); | |
| 1656 void MarkDefinition(Definition* defn); | |
| 1657 | |
| 1658 static GrowthDirection ToGrowthDirection(Value* val); | |
| 1659 | |
| 1660 static GrowthDirection Invert(GrowthDirection direction) { | |
| 1661 return (direction == POSITIVE) ? NEGATIVE : POSITIVE; | |
| 1662 } | |
| 1663 | |
| 1664 static void UpdateDirection(GrowthDirection* direction, | |
| 1665 GrowthDirection new_direction) { | |
| 1666 if (*direction != new_direction) { | |
| 1667 if (*direction != UNKNOWN) new_direction = BOTH; | |
| 1668 *direction = new_direction; | |
| 1669 } | |
| 1670 } | |
| 1646 | 1671 |
| 1647 // Remove artificial Constraint instructions and replace them with actual | 1672 // Remove artificial Constraint instructions and replace them with actual |
| 1648 // unconstrained definitions. | 1673 // unconstrained definitions. |
| 1649 void RemoveConstraints(); | 1674 void RemoveConstraints(); |
| 1650 | 1675 |
| 1651 void CreateWorklists(); | |
| 1652 | |
| 1653 void AddToWorklist(Definition* value) { | |
| 1654 const intptr_t index = value->ssa_temp_index(); | |
| 1655 if (!in_worklist_->Contains(index)) { | |
| 1656 in_worklist_->Add(index); | |
| 1657 worklist_.Add(value); | |
| 1658 } | |
| 1659 } | |
| 1660 | |
| 1661 bool IsWorklistEmpty() const { | |
| 1662 return worklist_.is_empty(); | |
| 1663 } | |
| 1664 | |
| 1665 Definition* RemoveLastFromWorklist() { | |
| 1666 Definition* defn = worklist_.Last(); | |
| 1667 worklist_.RemoveLast(); | |
| 1668 ASSERT(in_worklist_->Contains(defn->ssa_temp_index())); | |
| 1669 in_worklist_->Remove(defn->ssa_temp_index()); | |
| 1670 return defn; | |
| 1671 } | |
| 1672 | |
| 1673 void SwapWorklists(); | |
| 1674 | |
| 1675 FlowGraph* flow_graph_; | 1676 FlowGraph* flow_graph_; |
| 1676 | 1677 |
| 1677 GrowableArray<Definition*> smi_values_; // Value that are known to be smi. | 1678 GrowableArray<Definition*> smi_values_; // Value that are known to be smi. |
| 1678 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions. | 1679 GrowableArray<CheckSmiInstr*> smi_checks_; // All CheckSmi instructions. |
| 1679 | 1680 |
| 1680 // All Constraints inserted during InsertConstraints phase. They are treated | 1681 // All Constraints inserted during InsertConstraints phase. They are treated |
| 1681 // as smi values. | 1682 // as smi values. |
| 1682 GrowableArray<ConstraintInstr*> constraints_; | 1683 GrowableArray<ConstraintInstr*> constraints_; |
| 1683 | 1684 |
| 1684 // Bitvector for a quick filtering of known smi values. | 1685 // Bitvector for a quick filtering of known smi values. |
| 1685 BitVector* smi_definitions_; | 1686 BitVector* smi_definitions_; |
| 1686 | 1687 |
| 1687 // Worklist used during range propagation. | 1688 // Worklist for induction variables analysis. |
| 1688 GrowableArray<Definition*> worklist_; | 1689 GrowableArray<Definition*> worklist_; |
| 1689 BitVector* in_worklist_; | 1690 BitVector* marked_defns_; |
| 1690 | 1691 |
| 1691 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); | 1692 DISALLOW_COPY_AND_ASSIGN(RangeAnalysis); |
| 1692 }; | 1693 }; |
| 1693 | 1694 |
| 1694 | 1695 |
| 1695 void RangeAnalysis::Analyze() { | 1696 void RangeAnalysis::Analyze() { |
| 1696 CollectSmiValues(); | 1697 CollectSmiValues(); |
| 1697 InsertConstraints(); | 1698 InsertConstraints(); |
| 1698 InferRanges(); | 1699 InferRanges(); |
| 1699 RemoveConstraints(); | 1700 RemoveConstraints(); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1934 InsertConstraintsFor(constraint); // Constrain uses further. | 1935 InsertConstraintsFor(constraint); // Constrain uses further. |
| 1935 } | 1936 } |
| 1936 } | 1937 } |
| 1937 | 1938 |
| 1938 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 1939 for (intptr_t i = 0; i < smi_values_.length(); i++) { |
| 1939 InsertConstraintsFor(smi_values_[i]); | 1940 InsertConstraintsFor(smi_values_[i]); |
| 1940 } | 1941 } |
| 1941 } | 1942 } |
| 1942 | 1943 |
| 1943 | 1944 |
| 1944 void RangeAnalysis::InitializeRangesRecursive(BlockEntryInstr* block) { | 1945 void RangeAnalysis::ResetWorklist() { |
| 1946 if (marked_defns_ == NULL) { | |
| 1947 marked_defns_ = new BitVector(flow_graph_->current_ssa_temp_index()); | |
| 1948 } else { | |
| 1949 marked_defns_->Clear(); | |
| 1950 } | |
| 1951 worklist_.Clear(); | |
| 1952 } | |
| 1953 | |
| 1954 | |
| 1955 void RangeAnalysis::MarkDefinition(Definition* defn) { | |
| 1956 // Unwrap constrained value. | |
| 1957 while (defn->IsConstraint()) { | |
| 1958 defn = defn->AsConstraint()->value()->definition(); | |
| 1959 } | |
| 1960 | |
| 1961 if (!marked_defns_->Contains(defn->ssa_temp_index())) { | |
| 1962 worklist_.Add(defn); | |
| 1963 marked_defns_->Add(defn->ssa_temp_index()); | |
| 1964 } | |
| 1965 } | |
| 1966 | |
| 1967 | |
| 1968 RangeAnalysis::GrowthDirection RangeAnalysis::ToGrowthDirection(Value* val) { | |
| 1969 if (val->BindsToConstant()) { | |
| 1970 return (Smi::Cast(val->BoundConstant()).Value() >= 0) ? POSITIVE : NEGATIVE; | |
| 1971 } else if (val->definition()->range() != NULL) { | |
| 1972 Range* range = val->definition()->range(); | |
| 1973 if (Range::ConstantMin(range).value() >= 0) { | |
| 1974 return POSITIVE; | |
| 1975 } else if (Range::ConstantMax(range).value() <= 0) { | |
| 1976 return NEGATIVE; | |
| 1977 } | |
| 1978 } | |
| 1979 return UNKNOWN; | |
| 1980 } | |
| 1981 | |
| 1982 | |
| 1983 Range* RangeAnalysis::InferInductionVariableRange(JoinEntryInstr* loop_header, | |
| 1984 PhiInstr* var) { | |
| 1985 BitVector* loop_info = loop_header->loop_info(); | |
| 1986 | |
| 1987 Definition* initial_value = NULL; | |
| 1988 GrowthDirection direction = UNKNOWN; | |
| 1989 | |
| 1990 ResetWorklist(); | |
| 1991 MarkDefinition(var); | |
| 1992 while (!worklist_.is_empty()) { | |
| 1993 Definition* defn = worklist_.Last(); | |
| 1994 worklist_.RemoveLast(); | |
| 1995 | |
| 1996 if (defn->IsPhi()) { | |
| 1997 PhiInstr* phi = defn->AsPhi(); | |
| 1998 for (intptr_t i = 0; i < phi->InputCount(); i++) { | |
| 1999 Definition* defn = phi->InputAt(i)->definition(); | |
| 2000 | |
| 2001 if (!loop_info->Contains(defn->GetBlock()->preorder_number())) { | |
| 2002 // The value is comming from outside of the loop. | |
|
Florian Schneider
2012/10/25 11:15:43
s/comming/coming/
Vyacheslav Egorov (Google)
2012/10/25 11:24:27
Done.
| |
| 2003 if (initial_value == NULL) { | |
| 2004 initial_value = defn; | |
| 2005 continue; | |
| 2006 } else if (initial_value == defn) { | |
| 2007 continue; | |
| 2008 } else { | |
| 2009 return NULL; | |
| 2010 } | |
| 2011 } | |
| 2012 | |
| 2013 MarkDefinition(defn); | |
| 2014 } | |
| 2015 } else if (defn->IsBinarySmiOp()) { | |
| 2016 BinarySmiOpInstr* binary_op = defn->AsBinarySmiOp(); | |
| 2017 | |
| 2018 switch (binary_op->op_kind()) { | |
| 2019 case Token::kADD: { | |
| 2020 const GrowthDirection growth_right = | |
| 2021 ToGrowthDirection(binary_op->right()); | |
| 2022 if (growth_right != UNKNOWN) { | |
| 2023 UpdateDirection(&direction, growth_right); | |
| 2024 MarkDefinition(binary_op->left()->definition()); | |
| 2025 break; | |
| 2026 } | |
| 2027 | |
| 2028 const GrowthDirection growth_left = | |
| 2029 ToGrowthDirection(binary_op->left()); | |
| 2030 if (growth_left != UNKNOWN) { | |
| 2031 UpdateDirection(&direction, growth_left); | |
| 2032 MarkDefinition(binary_op->right()->definition()); | |
| 2033 break; | |
| 2034 } | |
| 2035 | |
| 2036 return NULL; | |
| 2037 } | |
| 2038 | |
| 2039 case Token::kSUB: { | |
| 2040 const GrowthDirection growth_right = | |
| 2041 ToGrowthDirection(binary_op->right()); | |
| 2042 if (growth_right != UNKNOWN) { | |
| 2043 UpdateDirection(&direction, Invert(growth_right)); | |
| 2044 MarkDefinition(binary_op->left()->definition()); | |
| 2045 break; | |
| 2046 } | |
| 2047 return NULL; | |
| 2048 } | |
| 2049 | |
| 2050 default: | |
| 2051 return NULL; | |
| 2052 } | |
| 2053 } else { | |
| 2054 return NULL; | |
| 2055 } | |
| 2056 } | |
| 2057 | |
| 2058 | |
| 2059 // We transitively discovered all dependecies of the given phi | |
|
Florian Schneider
2012/10/25 11:15:43
s/dependecies/dependencies/
Vyacheslav Egorov (Google)
2012/10/25 11:24:27
Done.
| |
| 2060 // and confirmed that it depends on a sigle value comming from outside of | |
|
Florian Schneider
2012/10/25 11:15:43
s/sigle/single/
s/comming/coming/g
Vyacheslav Egorov (Google)
2012/10/25 11:24:27
Done.
| |
| 2061 // the loop and some linear combinations of itself. | |
| 2062 // Compute the range based on initial value and the direction of the growth. | |
| 2063 switch (direction) { | |
| 2064 case POSITIVE: | |
| 2065 return new Range(RangeBoundary::FromDefinition(initial_value), | |
| 2066 RangeBoundary::MaxSmi()); | |
| 2067 | |
| 2068 case NEGATIVE: | |
| 2069 return new Range(RangeBoundary::MinSmi(), | |
| 2070 RangeBoundary::FromDefinition(initial_value)); | |
| 2071 | |
| 2072 case UNKNOWN: | |
| 2073 case BOTH: | |
| 2074 return Range::Unknown(); | |
| 2075 } | |
| 2076 | |
| 2077 UNREACHABLE(); | |
| 2078 return NULL; | |
| 2079 } | |
| 2080 | |
| 2081 | |
| 2082 void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) { | |
| 1945 JoinEntryInstr* join = block->AsJoinEntry(); | 2083 JoinEntryInstr* join = block->AsJoinEntry(); |
| 1946 if (join != NULL) { | 2084 if (join != NULL) { |
| 2085 const bool is_loop_header = (join->loop_info() != NULL); | |
| 1947 for (PhiIterator it(join); !it.Done(); it.Advance()) { | 2086 for (PhiIterator it(join); !it.Done(); it.Advance()) { |
| 1948 PhiInstr* phi = it.Current(); | 2087 PhiInstr* phi = it.Current(); |
| 1949 if (smi_definitions_->Contains(phi->ssa_temp_index())) { | 2088 if (smi_definitions_->Contains(phi->ssa_temp_index())) { |
| 1950 phi->InferRange(Definition::kRangeInit); | 2089 if (is_loop_header) { |
| 1951 AddToWorklist(phi); | 2090 // Try recognizing simple induction variables. |
| 2091 Range* range = InferInductionVariableRange(join, phi); | |
| 2092 if (range != NULL) { | |
| 2093 phi->range_ = range; | |
| 2094 continue; | |
| 2095 } | |
| 2096 } | |
| 2097 | |
| 2098 phi->InferRange(); | |
| 1952 } | 2099 } |
| 1953 } | 2100 } |
| 1954 } | 2101 } |
| 1955 | 2102 |
| 1956 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 2103 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
| 1957 Definition* defn = it.Current()->AsDefinition(); | 2104 Definition* defn = it.Current()->AsDefinition(); |
| 1958 if ((defn != NULL) && | 2105 if ((defn != NULL) && |
| 1959 (defn->ssa_temp_index() != -1) && | 2106 (defn->ssa_temp_index() != -1) && |
| 1960 smi_definitions_->Contains(defn->ssa_temp_index())) { | 2107 smi_definitions_->Contains(defn->ssa_temp_index())) { |
| 1961 defn->InferRange(Definition::kRangeInit); | 2108 defn->InferRange(); |
| 1962 AddToWorklist(defn); | |
| 1963 } | 2109 } |
| 1964 } | 2110 } |
| 1965 | 2111 |
| 1966 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { | 2112 for (intptr_t i = 0; i < block->dominated_blocks().length(); ++i) { |
| 1967 InitializeRangesRecursive(block->dominated_blocks()[i]); | 2113 InferRangesRecursive(block->dominated_blocks()[i]); |
| 1968 } | |
| 1969 } | |
| 1970 | |
| 1971 | |
| 1972 void RangeAnalysis::CreateWorklists() { | |
| 1973 in_worklist_ = new BitVector(flow_graph_->current_ssa_temp_index()); | |
| 1974 } | |
| 1975 | |
| 1976 | |
| 1977 void RangeAnalysis::ProcessWorklist(Definition::RangeOperator op) { | |
| 1978 // Iterate until fix point is reached. | |
| 1979 while (!IsWorklistEmpty()) { | |
| 1980 Definition* defn = RemoveLastFromWorklist(); | |
| 1981 if (FLAG_trace_range_analysis) { | |
| 1982 OS::Print("infering range for v%"Pd" %s\n", | |
| 1983 defn->ssa_temp_index(), | |
| 1984 Range::ToCString(defn->range())); | |
| 1985 } | |
| 1986 if (defn->InferRange(op)) { // Update the range. | |
| 1987 if (FLAG_trace_range_analysis) { | |
| 1988 OS::Print(" changed to %s\n", Range::ToCString(defn->range())); | |
| 1989 } | |
| 1990 // Range change. Place all uses to the worklist. | |
| 1991 for (Value* use = defn->input_use_list(); | |
| 1992 use != NULL; | |
| 1993 use = use->next_use()) { | |
| 1994 Definition* use_defn = use->instruction()->AsDefinition(); | |
| 1995 if ((use_defn != NULL) && | |
| 1996 (use_defn->ssa_temp_index() != -1) && | |
| 1997 smi_definitions_->Contains(use_defn->ssa_temp_index())) { | |
| 1998 AddToWorklist(use_defn); | |
| 1999 } | |
| 2000 } | |
| 2001 } | |
| 2002 } | 2114 } |
| 2003 } | 2115 } |
| 2004 | 2116 |
| 2005 | 2117 |
| 2006 void RangeAnalysis::InferRanges() { | 2118 void RangeAnalysis::InferRanges() { |
| 2007 CreateWorklists(); | |
| 2008 | |
| 2009 // Initialize bitvector for quick filtering of smi values. | 2119 // Initialize bitvector for quick filtering of smi values. |
| 2010 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index()); | 2120 smi_definitions_ = new BitVector(flow_graph_->current_ssa_temp_index()); |
| 2011 for (intptr_t i = 0; i < smi_values_.length(); i++) { | 2121 for (intptr_t i = 0; i < smi_values_.length(); i++) { |
| 2012 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); | 2122 smi_definitions_->Add(smi_values_[i]->ssa_temp_index()); |
| 2013 } | 2123 } |
| 2014 for (intptr_t i = 0; i < constraints_.length(); i++) { | 2124 for (intptr_t i = 0; i < constraints_.length(); i++) { |
| 2015 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); | 2125 smi_definitions_->Add(constraints_[i]->ssa_temp_index()); |
| 2016 } | 2126 } |
| 2017 | 2127 |
| 2018 // Infer initial values of ranges. | 2128 // Infer initial values of ranges. |
| 2019 InitializeRangesRecursive(flow_graph_->graph_entry()); | 2129 InferRangesRecursive(flow_graph_->graph_entry()); |
| 2020 | |
| 2021 for (intptr_t i = 0; i < smi_values_.length(); i++) { | |
| 2022 if (smi_values_[i]->IsPhi() && | |
| 2023 smi_values_[i]->InferRange(Definition::kRangeInit)) { | |
| 2024 Definition* defn = smi_values_[i]; | |
| 2025 for (Value* use = defn->input_use_list(); | |
| 2026 use != NULL; | |
| 2027 use = use->next_use()) { | |
| 2028 Definition* use_defn = use->instruction()->AsDefinition(); | |
| 2029 if ((use_defn != NULL) && | |
| 2030 (use_defn->ssa_temp_index() != -1) && | |
| 2031 smi_definitions_->Contains(use_defn->ssa_temp_index())) { | |
| 2032 AddToWorklist(use_defn); | |
| 2033 } | |
| 2034 } | |
| 2035 } | |
| 2036 } | |
| 2037 | 2130 |
| 2038 if (FLAG_trace_range_analysis) { | 2131 if (FLAG_trace_range_analysis) { |
| 2039 OS::Print("---- after initialization -------\n"); | 2132 OS::Print("---- after range analysis -------\n"); |
| 2040 FlowGraphPrinter printer(*flow_graph_); | 2133 FlowGraphPrinter printer(*flow_graph_); |
| 2041 printer.PrintBlocks(); | 2134 printer.PrintBlocks(); |
| 2042 } | 2135 } |
| 2043 | |
| 2044 if (FLAG_trace_range_analysis) { | |
| 2045 OS::Print("---- widening ---------\n"); | |
| 2046 } | |
| 2047 ProcessWorklist(Definition::kRangeWiden); | |
| 2048 | |
| 2049 if (FLAG_trace_range_analysis) { | |
| 2050 OS::Print("---- after widening -------\n"); | |
| 2051 FlowGraphPrinter printer(*flow_graph_); | |
| 2052 printer.PrintBlocks(); | |
| 2053 } | |
| 2054 | |
| 2055 if (FLAG_trace_range_analysis) { | |
| 2056 OS::Print("---- narrowing ---------\n"); | |
| 2057 } | |
| 2058 // Only phis can change under narrowing operator. Place all phis | |
| 2059 // into the worklist. | |
| 2060 for (intptr_t i = 0; i < smi_values_.length(); i++) { | |
| 2061 if (smi_values_[i]->IsPhi()) AddToWorklist(smi_values_[i]); | |
| 2062 } | |
| 2063 ProcessWorklist(Definition::kRangeNarrow); | |
| 2064 | |
| 2065 if (FLAG_trace_range_analysis) { | |
| 2066 OS::Print("---- after narrowing -------\n"); | |
| 2067 FlowGraphPrinter printer(*flow_graph_); | |
| 2068 printer.PrintBlocks(); | |
| 2069 } | |
| 2070 } | 2136 } |
| 2071 | 2137 |
| 2072 | 2138 |
| 2073 void RangeAnalysis::RemoveConstraints() { | 2139 void RangeAnalysis::RemoveConstraints() { |
| 2074 for (intptr_t i = 0; i < constraints_.length(); i++) { | 2140 for (intptr_t i = 0; i < constraints_.length(); i++) { |
| 2075 Definition* def = constraints_[i]->value()->definition(); | 2141 Definition* def = constraints_[i]->value()->definition(); |
| 2076 // Some constraints might be constraining constraints. Unwind the chain of | 2142 // Some constraints might be constraining constraints. Unwind the chain of |
| 2077 // constraints until we reach the actual definition. | 2143 // constraints until we reach the actual definition. |
| 2078 while (def->IsConstraint()) { | 2144 while (def->IsConstraint()) { |
| 2079 def = def->AsConstraint()->value()->definition(); | 2145 def = def->AsConstraint()->value()->definition(); |
| (...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3474 | 3540 |
| 3475 if (FLAG_trace_constant_propagation) { | 3541 if (FLAG_trace_constant_propagation) { |
| 3476 OS::Print("\n==== After constant propagation ====\n"); | 3542 OS::Print("\n==== After constant propagation ====\n"); |
| 3477 FlowGraphPrinter printer(*graph_); | 3543 FlowGraphPrinter printer(*graph_); |
| 3478 printer.PrintBlocks(); | 3544 printer.PrintBlocks(); |
| 3479 } | 3545 } |
| 3480 } | 3546 } |
| 3481 | 3547 |
| 3482 | 3548 |
| 3483 } // namespace dart | 3549 } // namespace dart |
| OLD | NEW |