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

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

Issue 10946027: Revert "Initial implementation of sparse conditional constant propagation." (Closed) Base URL: https://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
« 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/intermediate_language.h"
13 #include "vm/object_store.h" 12 #include "vm/object_store.h"
14 #include "vm/parser.h" 13 #include "vm/parser.h"
15 #include "vm/scopes.h" 14 #include "vm/scopes.h"
16 #include "vm/symbols.h" 15 #include "vm/symbols.h"
17 16
18 namespace dart { 17 namespace dart {
19 18
20 DECLARE_FLAG(bool, eliminate_type_checks); 19 DECLARE_FLAG(bool, eliminate_type_checks);
21 DECLARE_FLAG(bool, enable_type_checks); 20 DECLARE_FLAG(bool, enable_type_checks);
22 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details."); 21 DEFINE_FLAG(bool, trace_optimization, false, "Print optimization details.");
(...skipping 1747 matching lines...) Expand 10 before | Expand all | Expand 10 after
1770 if (i < num_children - 1) { 1769 if (i < num_children - 1) {
1771 DirectChainedHashMap<Definition*> child_map(*map); // Copy map. 1770 DirectChainedHashMap<Definition*> child_map(*map); // Copy map.
1772 OptimizeRecursive(child, &child_map); 1771 OptimizeRecursive(child, &child_map);
1773 } else { 1772 } else {
1774 OptimizeRecursive(child, map); // Reuse map for the last child. 1773 OptimizeRecursive(child, map); // Reuse map for the last child.
1775 } 1774 }
1776 } 1775 }
1777 } 1776 }
1778 1777
1779 1778
1780 ConstantPropagator::ConstantPropagator(FlowGraph* graph)
1781 : FlowGraphVisitor(GrowableArray<BlockEntryInstr*>()),
1782 graph_(graph),
1783 unknown_(Object::ZoneHandle(Object::transition_sentinel())),
1784 non_constant_(Object::ZoneHandle(Object::sentinel())),
1785 reachable_(new BitVector(graph->preorder().length())),
1786 definition_marks_(new BitVector(graph->max_virtual_register_number())),
1787 block_worklist_(),
1788 definition_worklist_() {}
1789
1790
1791 void ConstantPropagator::SetReachable(BlockEntryInstr* block) {
1792 if (!reachable_->Contains(block->preorder_number())) {
1793 reachable_->Add(block->preorder_number());
1794 block_worklist_.Add(block);
1795 }
1796 }
1797
1798
1799 void ConstantPropagator::SetValue(Definition* definition, const Object& value) {
1800 // We would like to assert we only go up (toward non-constant) in the lattice.
1801 //
1802 // ASSERT(IsUnknown(definition->constant_value()) ||
1803 // IsNonConstant(value) ||
1804 // (definition->constant_value().raw() == value.raw()));
1805 //
1806 // But the final disjunct is not true (e.g., mint or double constants are
1807 // heap-allocated and so not necessarily pointer-equal on each iteration).
1808 if (definition->constant_value().raw() != value.raw()) {
1809 definition->constant_value() = value.raw();
1810 if (definition->input_use_list() != NULL) {
1811 ASSERT(definition->HasSSATemp());
1812 if (!definition_marks_->Contains(definition->ssa_temp_index())) {
1813 definition_worklist_.Add(definition);
1814 definition_marks_->Add(definition->ssa_temp_index());
1815 }
1816 }
1817 }
1818 }
1819
1820
1821 // Compute the join of two values in the lattice, assign it to the first.
1822 void ConstantPropagator::Join(Object* left, const Object& right) {
1823 // Join(non-constant, X) = non-constant
1824 // Join(X, unknown) = X
1825 if (IsNonConstant(*left) || IsUnknown(right)) return;
1826
1827 // Join(unknown, X) = X
1828 // Join(X, non-constant) = non-constant
1829 if (IsUnknown(*left) || IsNonConstant(right)) {
1830 *left = right.raw();
1831 return;
1832 }
1833
1834 // Join(X, X) = X
1835 // TODO(kmillikin): support equality for doubles, mints, etc.
1836 if (left->raw() == right.raw()) return;
1837
1838 // Join(X, Y) = non-constant
1839 *left = non_constant_.raw();
1840 }
1841
1842
1843 // --------------------------------------------------------------------------
1844 // Analysis of blocks. Called at most once per block. The block is already
1845 // marked as reachable. All instructions in the block are analyzed.
1846 void ConstantPropagator::VisitGraphEntry(GraphEntryInstr* block) {
1847 block->constant_null()->Accept(this);
1848 for (Environment::ShallowIterator it(block->start_env());
1849 !it.Done();
1850 it.Advance()) {
1851 it.CurrentValue()->definition()->Accept(this);
1852 }
1853 ASSERT(ForwardInstructionIterator(block).Done());
1854
1855 SetReachable(block->normal_entry());
1856 }
1857
1858
1859 void ConstantPropagator::VisitJoinEntry(JoinEntryInstr* block) {
1860 ZoneGrowableArray<PhiInstr*>* phis = block->phis();
1861 if (phis != NULL) {
1862 for (intptr_t phi_idx = 0; phi_idx < phis->length(); ++phi_idx) {
1863 PhiInstr* phi = (*phis)[phi_idx];
1864 if (phi == NULL) continue;
1865 phi->Accept(this);
1866 }
1867 }
1868
1869 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1870 it.Current()->Accept(this);
1871 }
1872 }
1873
1874
1875 void ConstantPropagator::VisitTargetEntry(TargetEntryInstr* block) {
1876 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
1877 it.Current()->Accept(this);
1878 }
1879 }
1880
1881
1882 void ConstantPropagator::VisitParallelMove(ParallelMoveInstr* instr) {
1883 // Parallel moves have not yet been inserted in the graph.
1884 UNREACHABLE();
1885 }
1886
1887
1888 // --------------------------------------------------------------------------
1889 // Analysis of control instructions. Unconditional successors are
1890 // reachable. Conditional successors are reachable depending on the
1891 // constant value of the condition.
1892 void ConstantPropagator::VisitReturn(ReturnInstr* instr) {
1893 // Nothing to do.
1894 }
1895
1896
1897 void ConstantPropagator::VisitThrow(ThrowInstr* instr) {
1898 // Nothing to do.
1899 }
1900
1901
1902 void ConstantPropagator::VisitReThrow(ReThrowInstr* instr) {
1903 // Nothing to do.
1904 }
1905
1906
1907 void ConstantPropagator::VisitGoto(GotoInstr* instr) {
1908 SetReachable(instr->successor());
1909 }
1910
1911
1912 void ConstantPropagator::VisitBranch(BranchInstr* instr) {
1913 instr->comparison()->Accept(this);
1914 const Object& value = instr->comparison()->constant_value();
1915 if (IsNonConstant(value)) {
1916 SetReachable(instr->true_successor());
1917 SetReachable(instr->false_successor());
1918 } else if (value.raw() == Bool::True()) {
1919 SetReachable(instr->true_successor());
1920 } else if (!IsUnknown(value)) { // Any other constant.
1921 SetReachable(instr->false_successor());
1922 }
1923 }
1924
1925
1926 // --------------------------------------------------------------------------
1927 // Analysis of definitions. Compute the constant value. If it has changed
1928 // and the definition has input uses, add the definition to the definition
1929 // worklist so that the used can be processed.
1930 void ConstantPropagator::VisitPhi(PhiInstr* instr) {
1931 // Compute the join over all the reachable predecessor values.
1932 JoinEntryInstr* block = instr->block();
1933 Object& value = Object::ZoneHandle(Unknown());
1934 for (intptr_t pred_idx = 0; pred_idx < instr->InputCount(); ++pred_idx) {
1935 if (reachable_->Contains(
1936 block->PredecessorAt(pred_idx)->preorder_number())) {
1937 Join(&value,
1938 instr->InputAt(pred_idx)->definition()->constant_value());
1939 }
1940 }
1941 SetValue(instr, value);
1942 }
1943
1944
1945 void ConstantPropagator::VisitParameter(ParameterInstr* instr) {
1946 SetValue(instr, non_constant_);
1947 }
1948
1949
1950 void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) {
1951 SetValue(instr, instr->value()->definition()->constant_value());
1952 }
1953
1954
1955 void ConstantPropagator::VisitAssertAssignable(AssertAssignableInstr* instr) {
1956 const Object& value = instr->value()->definition()->constant_value();
1957 if (IsNonConstant(value)) {
1958 SetValue(instr, non_constant_);
1959 } else if (IsConstant(value)) {
1960 // We are ignoring the instantiator and instantiator_type_arguments, but
1961 // still monotonic and safe.
1962 // TODO(kmillikin): Handle constants.
1963 SetValue(instr, non_constant_);
1964 }
1965 }
1966
1967
1968 void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
1969 const Object& value = instr->value()->definition()->constant_value();
1970 if (IsNonConstant(value)) {
1971 SetValue(instr, non_constant_);
1972 } else if (IsConstant(value)) {
1973 // TODO(kmillikin): Handle assertion.
1974 SetValue(instr, non_constant_);
1975 }
1976 }
1977
1978
1979 void ConstantPropagator::VisitArgumentDefinitionTest(
1980 ArgumentDefinitionTestInstr* instr) {
1981 SetValue(instr, non_constant_);
1982 }
1983
1984
1985 void ConstantPropagator::VisitCurrentContext(CurrentContextInstr* instr) {
1986 SetValue(instr, non_constant_);
1987 }
1988
1989
1990 void ConstantPropagator::VisitStoreContext(StoreContextInstr* instr) {
1991 SetValue(instr, non_constant_);
1992 }
1993
1994
1995 void ConstantPropagator::VisitClosureCall(ClosureCallInstr* instr) {
1996 SetValue(instr, non_constant_);
1997 }
1998
1999
2000 void ConstantPropagator::VisitInstanceCall(InstanceCallInstr* instr) {
2001 SetValue(instr, non_constant_);
2002 }
2003
2004
2005 void ConstantPropagator::VisitPolymorphicInstanceCall(
2006 PolymorphicInstanceCallInstr* instr) {
2007 SetValue(instr, non_constant_);
2008 }
2009
2010
2011 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) {
2012 SetValue(instr, non_constant_);
2013 }
2014
2015
2016 void ConstantPropagator::VisitLoadLocal(LoadLocalInstr* instr) {
2017 UNREACHABLE();
2018 }
2019
2020
2021 void ConstantPropagator::VisitStoreLocal(StoreLocalInstr* instr) {
2022 UNREACHABLE();
2023 }
2024
2025
2026 void ConstantPropagator::VisitStrictCompare(StrictCompareInstr* instr) {
2027 const Object& left = instr->left()->definition()->constant_value();
2028 const Object& right = instr->right()->definition()->constant_value();
2029 if (IsNonConstant(left) || IsNonConstant(right)) {
2030 SetValue(instr, non_constant_);
2031 } else if (IsConstant(left) && IsConstant(right)) {
2032 bool result = (left.raw() == right.raw());
2033 if (instr->kind() == Token::kNE_STRICT) result = !result;
2034 SetValue(instr, Bool::ZoneHandle(Bool::Get(result)));
2035 }
2036 }
2037
2038
2039 void ConstantPropagator::VisitEqualityCompare(EqualityCompareInstr* instr) {
2040 const Object& left = instr->left()->definition()->constant_value();
2041 const Object& right = instr->right()->definition()->constant_value();
2042 if (IsNonConstant(left) || IsNonConstant(right)) {
2043 SetValue(instr, non_constant_);
2044 } else if (IsConstant(left) && IsConstant(right)) {
2045 // TODO(kmillikin): Handle equality comparison of constants.
2046 SetValue(instr, non_constant_);
2047 }
2048 }
2049
2050
2051 void ConstantPropagator::VisitRelationalOp(RelationalOpInstr* instr) {
2052 const Object& left = instr->left()->definition()->constant_value();
2053 const Object& right = instr->right()->definition()->constant_value();
2054 if (IsNonConstant(left) || IsNonConstant(right)) {
2055 SetValue(instr, non_constant_);
2056 } else if (IsConstant(left) && IsConstant(right)) {
2057 // TODO(kmillikin): Handle relational comparison of constants.
2058 SetValue(instr, non_constant_);
2059 }
2060 }
2061
2062
2063 void ConstantPropagator::VisitNativeCall(NativeCallInstr* instr) {
2064 SetValue(instr, non_constant_);
2065 }
2066
2067
2068 void ConstantPropagator::VisitLoadIndexed(LoadIndexedInstr* instr) {
2069 SetValue(instr, non_constant_);
2070 }
2071
2072
2073 void ConstantPropagator::VisitStoreIndexed(StoreIndexedInstr* instr) {
2074 SetValue(instr, instr->value()->definition()->constant_value());
2075 }
2076
2077
2078 void ConstantPropagator::VisitStoreInstanceField(
2079 StoreInstanceFieldInstr* instr) {
2080 SetValue(instr, instr->value()->definition()->constant_value());
2081 }
2082
2083
2084 void ConstantPropagator::VisitLoadStaticField(LoadStaticFieldInstr* instr) {
2085 SetValue(instr, non_constant_);
2086 }
2087
2088
2089 void ConstantPropagator::VisitStoreStaticField(StoreStaticFieldInstr* instr) {
2090 SetValue(instr, instr->value()->definition()->constant_value());
2091 }
2092
2093
2094 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) {
2095 const Object& value = instr->value()->definition()->constant_value();
2096 if (IsNonConstant(value)) {
2097 SetValue(instr, non_constant_);
2098 } else if (IsConstant(value)) {
2099 SetValue(instr, Bool::ZoneHandle(Bool::Get(value.raw() != Bool::True())));
2100 }
2101 }
2102
2103
2104 void ConstantPropagator::VisitInstanceOf(InstanceOfInstr* instr) {
2105 const Object& value = instr->value()->definition()->constant_value();
2106 if (IsNonConstant(value)) {
2107 SetValue(instr, non_constant_);
2108 } else if (IsConstant(value)) {
2109 // TODO(kmillikin): Handle instanceof on constants.
2110 SetValue(instr, non_constant_);
2111 }
2112 }
2113
2114
2115 void ConstantPropagator::VisitCreateArray(CreateArrayInstr* instr) {
2116 SetValue(instr, non_constant_);
2117 }
2118
2119
2120 void ConstantPropagator::VisitCreateClosure(CreateClosureInstr* instr) {
2121 // TODO(kmillikin): Treat closures as constants.
2122 SetValue(instr, non_constant_);
2123 }
2124
2125
2126 void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) {
2127 SetValue(instr, non_constant_);
2128 }
2129
2130
2131 void ConstantPropagator::VisitAllocateObjectWithBoundsCheck(
2132 AllocateObjectWithBoundsCheckInstr* instr) {
2133 SetValue(instr, non_constant_);
2134 }
2135
2136
2137 void ConstantPropagator::VisitLoadField(LoadFieldInstr* instr) {
2138 SetValue(instr, non_constant_);
2139 }
2140
2141
2142 void ConstantPropagator::VisitStoreVMField(StoreVMFieldInstr* instr) {
2143 SetValue(instr, instr->value()->definition()->constant_value());
2144 }
2145
2146
2147 void ConstantPropagator::VisitInstantiateTypeArguments(
2148 InstantiateTypeArgumentsInstr* instr) {
2149 SetValue(instr, non_constant_);
2150 }
2151
2152
2153 void ConstantPropagator::VisitExtractConstructorTypeArguments(
2154 ExtractConstructorTypeArgumentsInstr* instr) {
2155 SetValue(instr, non_constant_);
2156 }
2157
2158
2159 void ConstantPropagator::VisitExtractConstructorInstantiator(
2160 ExtractConstructorInstantiatorInstr* instr) {
2161 SetValue(instr, non_constant_);
2162 }
2163
2164
2165 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) {
2166 SetValue(instr, non_constant_);
2167 }
2168
2169
2170 void ConstantPropagator::VisitChainContext(ChainContextInstr* instr) {
2171 SetValue(instr, non_constant_);
2172 }
2173
2174
2175 void ConstantPropagator::VisitCloneContext(CloneContextInstr* instr) {
2176 SetValue(instr, non_constant_);
2177 }
2178
2179
2180 void ConstantPropagator::VisitCatchEntry(CatchEntryInstr* instr) {
2181 SetValue(instr, non_constant_);
2182 }
2183
2184
2185 void ConstantPropagator::VisitBinarySmiOp(BinarySmiOpInstr* instr) {
2186 const Object& left = instr->left()->definition()->constant_value();
2187 const Object& right = instr->right()->definition()->constant_value();
2188 if (IsNonConstant(left) || IsNonConstant(right)) {
2189 SetValue(instr, non_constant_);
2190 } else if (IsConstant(left) && IsConstant(right)) {
2191 if (left.IsSmi() && right.IsSmi()) {
2192 switch (instr->op_kind()) {
2193 case Token::kADD:
2194 case Token::kSUB:
2195 case Token::kMUL:
2196 case Token::kTRUNCDIV:
2197 case Token::kMOD: {
2198 const Object& result =
2199 Integer::ZoneHandle(Integer::BinaryOp(instr->op_kind(),
2200 Smi::Cast(left),
2201 Smi::Cast(right)));
2202 SetValue(instr, result);
2203 break;
2204 }
2205 default:
2206 // TODO(kmillikin): support other smi operations.
2207 SetValue(instr, non_constant_);
2208 }
2209 } else {
2210 // TODO(kmillikin): support other types.
2211 SetValue(instr, non_constant_);
2212 }
2213 }
2214 }
2215
2216
2217 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) {
2218 const Object& left = instr->left()->definition()->constant_value();
2219 const Object& right = instr->right()->definition()->constant_value();
2220 if (IsNonConstant(left) || IsNonConstant(right)) {
2221 SetValue(instr, non_constant_);
2222 } else if (IsConstant(left) && IsConstant(right)) {
2223 // TODO(kmillikin): Handle binary operations.
2224 SetValue(instr, non_constant_);
2225 }
2226 }
2227
2228
2229 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) {
2230 const Object& value = instr->value()->definition()->constant_value();
2231 if (IsNonConstant(value)) {
2232 SetValue(instr, non_constant_);
2233 } else if (IsConstant(value)) {
2234 // TODO(kmillikin): Handle unary operations.
2235 SetValue(instr, non_constant_);
2236 }
2237 }
2238
2239
2240 void ConstantPropagator::VisitCheckStackOverflow(
2241 CheckStackOverflowInstr* instr) {
2242 SetValue(instr, non_constant_);
2243 }
2244
2245
2246 void ConstantPropagator::VisitDoubleToDouble(DoubleToDoubleInstr* instr) {
2247 const Object& value = instr->value()->definition()->constant_value();
2248 if (IsNonConstant(value)) {
2249 SetValue(instr, non_constant_);
2250 } else if (IsConstant(value)) {
2251 // TODO(kmillikin): Handle conversion.
2252 SetValue(instr, non_constant_);
2253 }
2254 }
2255
2256
2257 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) {
2258 // TODO(kmillikin): Handle conversion.
2259 SetValue(instr, non_constant_);
2260 }
2261
2262
2263 void ConstantPropagator::VisitCheckClass(CheckClassInstr* instr) {
2264 const Object& value = instr->value()->definition()->constant_value();
2265 if (IsNonConstant(value)) {
2266 SetValue(instr, non_constant_);
2267 } else if (IsConstant(value)) {
2268 // TODO(kmillikin): Handle check.
2269 SetValue(instr, non_constant_);
2270 }
2271 }
2272
2273
2274 void ConstantPropagator::VisitCheckSmi(CheckSmiInstr* instr) {
2275 const Object& value = instr->value()->definition()->constant_value();
2276 if (IsNonConstant(value)) {
2277 SetValue(instr, non_constant_);
2278 } else if (IsConstant(value)) {
2279 // TODO(kmillikin): Handle check.
2280 SetValue(instr, non_constant_);
2281 }
2282 }
2283
2284
2285 void ConstantPropagator::VisitConstant(ConstantInstr* instr) {
2286 SetValue(instr, instr->value());
2287 }
2288
2289
2290 void ConstantPropagator::VisitCheckEitherNonSmi(CheckEitherNonSmiInstr* instr) {
2291 const Object& left = instr->left()->definition()->constant_value();
2292 const Object& right = instr->right()->definition()->constant_value();
2293 if (IsNonConstant(left) || IsNonConstant(right)) {
2294 SetValue(instr, non_constant_);
2295 } else if (IsConstant(left) && IsConstant(right)) {
2296 // TODO(kmillikin): Handle check.
2297 SetValue(instr, non_constant_);
2298 }
2299 }
2300
2301
2302 void ConstantPropagator::VisitUnboxedDoubleBinaryOp(
2303 UnboxedDoubleBinaryOpInstr* instr) {
2304 const Object& left = instr->left()->definition()->constant_value();
2305 const Object& right = instr->right()->definition()->constant_value();
2306 if (IsNonConstant(left) || IsNonConstant(right)) {
2307 SetValue(instr, non_constant_);
2308 } else if (IsConstant(left) && IsConstant(right)) {
2309 // TODO(kmillikin): Handle binary operation.
2310 SetValue(instr, non_constant_);
2311 }
2312 }
2313
2314
2315 void ConstantPropagator::VisitMathSqrt(MathSqrtInstr* instr) {
2316 const Object& value = instr->value()->definition()->constant_value();
2317 if (IsNonConstant(value)) {
2318 SetValue(instr, non_constant_);
2319 } else if (IsConstant(value)) {
2320 // TODO(kmillikin): Handle sqrt.
2321 SetValue(instr, non_constant_);
2322 }
2323 }
2324
2325
2326 void ConstantPropagator::VisitUnboxDouble(UnboxDoubleInstr* instr) {
2327 const Object& value = instr->value()->definition()->constant_value();
2328 if (IsNonConstant(value)) {
2329 SetValue(instr, non_constant_);
2330 } else if (IsConstant(value)) {
2331 // TODO(kmillikin): Handle conversion.
2332 SetValue(instr, non_constant_);
2333 }
2334 }
2335
2336
2337 void ConstantPropagator::VisitBoxDouble(BoxDoubleInstr* instr) {
2338 const Object& value = instr->value()->definition()->constant_value();
2339 if (IsNonConstant(value)) {
2340 SetValue(instr, non_constant_);
2341 } else if (IsConstant(value)) {
2342 // TODO(kmillikin): Handle conversion.
2343 SetValue(instr, non_constant_);
2344 }
2345 }
2346
2347
2348 void ConstantPropagator::VisitCheckArrayBound(CheckArrayBoundInstr* instr) {
2349 // TODO(kmillikin): Handle checks.
2350 SetValue(instr, non_constant_);
2351 }
2352
2353
2354 void ConstantPropagator::Analyze() {
2355 GraphEntryInstr* entry = graph_->graph_entry();
2356 reachable_->Add(entry->preorder_number());
2357 block_worklist_.Add(entry);
2358
2359 while (true) {
2360 if (block_worklist_.is_empty()) {
2361 if (definition_worklist_.is_empty()) break;
2362 Definition* definition = definition_worklist_.Last();
2363 definition_worklist_.RemoveLast();
2364 definition_marks_->Remove(definition->ssa_temp_index());
2365 Value* use = definition->input_use_list();
2366 while (use != NULL) {
2367 use->instruction()->Accept(this);
2368 use = use->next_use();
2369 }
2370 } else {
2371 BlockEntryInstr* block = block_worklist_.Last();
2372 block_worklist_.RemoveLast();
2373 block->Accept(this);
2374 }
2375 }
2376 }
2377
2378
2379 void ConstantPropagator::Transform() {
2380 // We will recompute dominators, block ordering, block ids, block last
2381 // instructions, previous pointers, predecessors, etc. after eliminating
2382 // unreachable code. We do not maintain those properties during the
2383 // transformation.
2384 for (BlockIterator b = graph_->reverse_postorder_iterator();
2385 !b.Done();
2386 b.Advance()) {
2387 BlockEntryInstr* block = b.Current();
2388 if (!reachable_->Contains(block->preorder_number())) {
2389 continue;
2390 }
2391 for (ForwardInstructionIterator i(block); !i.Done(); i.Advance()) {
2392 Definition* defn = i.Current()->AsDefinition();
2393 BranchInstr* branch = i.Current()->AsBranch();
2394 if (defn != NULL) {
2395 if (IsConstant(defn->constant_value())) {
2396 if (!defn->IsConstant() &&
2397 !defn->IsPushArgument() &&
2398 !defn->IsStoreLocal() &&
2399 !defn->IsStoreIndexed() &&
2400 !defn->IsStoreInstanceField() &&
2401 !defn->IsStoreStaticField() &&
2402 !defn->IsStoreVMField()) {
2403 // TODO(kmillikin): propagate constants to replace instructions
2404 // without side effects.
2405 }
2406 }
2407 } else if (branch != NULL) {
2408 TargetEntryInstr* if_true = branch->true_successor();
2409 TargetEntryInstr* if_false = branch->false_successor();
2410 JoinEntryInstr* join = NULL;
2411 Instruction* next = NULL;
2412
2413 if (!reachable_->Contains(if_true->preorder_number())) {
2414 ASSERT(reachable_->Contains(if_false->preorder_number()));
2415 ASSERT(branch->comparison()->IsStrictCompare());
2416 ASSERT(if_false->parallel_move() == NULL);
2417 ASSERT(if_false->loop_info() == NULL);
2418 join = new JoinEntryInstr(if_false->try_index());
2419 next = if_false->next();
2420 } else if (!reachable_->Contains(if_false->preorder_number())) {
2421 ASSERT(branch->comparison()->IsStrictCompare());
2422 ASSERT(if_true->parallel_move() == NULL);
2423 ASSERT(if_true->loop_info() == NULL);
2424 join = new JoinEntryInstr(if_true->try_index());
2425 next = if_true->next();
2426 }
2427
2428 if (join != NULL) {
2429 // Replace the branch with a jump to the reachable successor.
2430 // Drop the comparison, which does not have side effects as long
2431 // as it is a strict compare (the only one we can determine is
2432 // constant with the current analysis).
2433 GotoInstr* jump = new GotoInstr(join);
2434 // Removing the branch from the graph will leave the iterator in a
2435 // state where current is detached from the graph. Since current
2436 // has no successors and neither does its replacement, that's
2437 // safe.
2438 Instruction* previous = branch->previous();
2439 branch->set_previous(NULL);
2440 previous->set_next(jump);
2441 // Replace the false target entry with the new join entry. We will
2442 // recompute the dominators after this pass.
2443 join->set_next(next);
2444 }
2445 }
2446 }
2447 }
2448 graph_->DiscoverBlocks();
2449 GrowableArray<BitVector*> dominance_frontier;
2450 graph_->ComputeDominators(&dominance_frontier);
2451
2452 // Garbage collect phi inputs corresponding to unreachable predecessors.
2453 // This is required because we assume that predecessor and phi indexes
2454 // align. Note that this does not necessarily eliminate all useless phis
2455 // (e.g., it does not eliminate phis that were originally inserted solely
2456 // due to an assignment on the now-unreachable path).
2457 for (BlockIterator it = graph_->reverse_postorder_iterator();
2458 !it.Done();
2459 it.Advance()) {
2460 JoinEntryInstr* join = it.Current()->AsJoinEntry();
2461 if (join != NULL) join->EliminateUnreachablePhiInputs();
2462 }
2463
2464 graph_->ComputeUseLists();
2465 }
2466
2467
2468 } // namespace dart 1779 } // 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