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

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

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