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

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

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

Powered by Google App Engine
This is Rietveld 408576698