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

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

Issue 2273943002: VM: More refactoring of recognized methods inlining. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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
« no previous file with comments | « no previous file | runtime/vm/flow_graph.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/aot_optimizer.h" 5 #include "vm/aot_optimizer.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/branch_optimizer.h" 8 #include "vm/branch_optimizer.h"
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 1198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 } 1209 }
1210 InvokeMathCFunctionInstr* invoke = 1210 InvokeMathCFunctionInstr* invoke =
1211 new(Z) InvokeMathCFunctionInstr(args, 1211 new(Z) InvokeMathCFunctionInstr(args,
1212 call->deopt_id(), 1212 call->deopt_id(),
1213 recognized_kind, 1213 recognized_kind,
1214 call->token_pos()); 1214 call->token_pos());
1215 ReplaceCall(call, invoke); 1215 ReplaceCall(call, invoke);
1216 } 1216 }
1217 1217
1218 1218
1219 static bool IsSupportedByteArrayViewCid(intptr_t cid) {
1220 switch (cid) {
1221 case kTypedDataInt8ArrayCid:
1222 case kTypedDataUint8ArrayCid:
1223 case kExternalTypedDataUint8ArrayCid:
1224 case kTypedDataUint8ClampedArrayCid:
1225 case kExternalTypedDataUint8ClampedArrayCid:
1226 case kTypedDataInt16ArrayCid:
1227 case kTypedDataUint16ArrayCid:
1228 case kTypedDataInt32ArrayCid:
1229 case kTypedDataUint32ArrayCid:
1230 case kTypedDataFloat32ArrayCid:
1231 case kTypedDataFloat64ArrayCid:
1232 case kTypedDataFloat32x4ArrayCid:
1233 case kTypedDataInt32x4ArrayCid:
1234 return true;
1235 default:
1236 return false;
1237 }
1238 }
1239
1240
1241 // Inline only simple, frequently called core library methods. 1219 // Inline only simple, frequently called core library methods.
1242 bool AotOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) { 1220 bool AotOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
1243 ASSERT(call->HasICData()); 1221 ASSERT(call->HasICData());
1244 const ICData& ic_data = *call->ic_data(); 1222 const ICData& ic_data = *call->ic_data();
1245 if (ic_data.NumberOfUsedChecks() != 1) { 1223 if (ic_data.NumberOfUsedChecks() != 1) {
1246 // No type feedback collected or multiple receivers/targets found. 1224 // No type feedback collected or multiple receivers/targets found.
1247 return false; 1225 return false;
1248 } 1226 }
1249 1227
1250 Function& target = Function::Handle(Z); 1228 Function& target = Function::Handle(Z);
1251 GrowableArray<intptr_t> class_ids; 1229 GrowableArray<intptr_t> class_ids;
1252 ic_data.GetCheckAt(0, &class_ids, &target); 1230 ic_data.GetCheckAt(0, &class_ids, &target);
1253 MethodRecognizer::Kind recognized_kind = 1231 MethodRecognizer::Kind recognized_kind =
1254 MethodRecognizer::RecognizeKind(target); 1232 MethodRecognizer::RecognizeKind(target);
1255 1233
1256 if ((recognized_kind == MethodRecognizer::kOneByteStringCodeUnitAt) ||
1257 (recognized_kind == MethodRecognizer::kTwoByteStringCodeUnitAt) ||
1258 (recognized_kind == MethodRecognizer::kExternalOneByteStringCodeUnitAt) ||
1259 (recognized_kind == MethodRecognizer::kExternalTwoByteStringCodeUnitAt) ||
1260 (recognized_kind == MethodRecognizer::kGrowableArraySetData) ||
1261 (recognized_kind == MethodRecognizer::kGrowableArraySetLength) ||
1262 (recognized_kind == MethodRecognizer::kSmi_bitAndFromSmi)) {
1263 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1264 flow_graph_, current_iterator(), call);
1265 }
1266
1267 if (recognized_kind == MethodRecognizer::kStringBaseCharAt) {
1268 ASSERT((class_ids[0] == kOneByteStringCid) ||
1269 (class_ids[0] == kTwoByteStringCid) ||
1270 (class_ids[0] == kExternalOneByteStringCid) ||
1271 (class_ids[0] == kExternalTwoByteStringCid));
1272 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1273 flow_graph_, current_iterator(), call);
1274 }
1275
1276 if (class_ids[0] == kOneByteStringCid) {
1277 if (recognized_kind == MethodRecognizer::kOneByteStringSetAt) {
1278 // This is an internal method, no need to check argument types nor
1279 // range.
1280 Definition* str = call->ArgumentAt(0);
1281 Definition* index = call->ArgumentAt(1);
1282 Definition* value = call->ArgumentAt(2);
1283 StoreIndexedInstr* store_op = new(Z) StoreIndexedInstr(
1284 new(Z) Value(str),
1285 new(Z) Value(index),
1286 new(Z) Value(value),
1287 kNoStoreBarrier,
1288 1, // Index scale
1289 kOneByteStringCid,
1290 call->deopt_id(),
1291 call->token_pos());
1292 ReplaceCall(call, store_op);
1293 return true;
1294 }
1295 return false;
1296 }
1297
1298 if (CanUnboxDouble() && 1234 if (CanUnboxDouble() &&
1299 (recognized_kind == MethodRecognizer::kIntegerToDouble)) { 1235 (recognized_kind == MethodRecognizer::kIntegerToDouble)) {
1300 if (class_ids[0] == kSmiCid) { 1236 if (class_ids[0] == kSmiCid) {
1301 AddReceiverCheck(call); 1237 AddReceiverCheck(call);
1302 ReplaceCall(call, 1238 ReplaceCall(call,
1303 new(Z) SmiToDoubleInstr( 1239 new(Z) SmiToDoubleInstr(
1304 new(Z) Value(call->ArgumentAt(0)), 1240 new(Z) Value(call->ArgumentAt(0)),
1305 call->token_pos())); 1241 call->token_pos()));
1306 return true; 1242 return true;
1307 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) { 1243 } else if ((class_ids[0] == kMintCid) && CanConvertUnboxedMintToDouble()) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 if (!TargetCPUFeatures::double_truncate_round_supported()) { 1282 if (!TargetCPUFeatures::double_truncate_round_supported()) {
1347 ReplaceWithMathCFunction(call, recognized_kind); 1283 ReplaceWithMathCFunction(call, recognized_kind);
1348 } else { 1284 } else {
1349 AddReceiverCheck(call); 1285 AddReceiverCheck(call);
1350 DoubleToDoubleInstr* d2d_instr = 1286 DoubleToDoubleInstr* d2d_instr =
1351 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)), 1287 new(Z) DoubleToDoubleInstr(new(Z) Value(call->ArgumentAt(0)),
1352 recognized_kind, call->deopt_id()); 1288 recognized_kind, call->deopt_id());
1353 ReplaceCall(call, d2d_instr); 1289 ReplaceCall(call, d2d_instr);
1354 } 1290 }
1355 return true; 1291 return true;
1356 case MethodRecognizer::kDoubleAdd:
1357 case MethodRecognizer::kDoubleSub:
1358 case MethodRecognizer::kDoubleMul:
1359 case MethodRecognizer::kDoubleDiv:
1360 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1361 flow_graph_, current_iterator(), call);
1362 default: 1292 default:
1363 // Unsupported method. 1293 break;
1364 return false;
1365 } 1294 }
1366 } 1295 }
1367 1296
1368 if (IsSupportedByteArrayViewCid(class_ids[0]) || 1297 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1369 (class_ids[0] == kFloat32x4Cid) || 1298 flow_graph_, current_iterator(), call);
1370 (class_ids[0] == kInt32x4Cid) ||
1371 (class_ids[0] == kFloat64x2Cid)) {
1372 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1373 flow_graph_, current_iterator(), call);
1374 }
1375
1376 return false;
1377 } 1299 }
1378 1300
1379 1301
1380 // If type tests specified by 'ic_data' do not depend on type arguments, 1302 // If type tests specified by 'ic_data' do not depend on type arguments,
1381 // return mapping cid->result in 'results' (i : cid; i + 1: result). 1303 // return mapping cid->result in 'results' (i : cid; i + 1: result).
1382 // If all tests yield the same result, return it otherwise return Bool::null. 1304 // If all tests yield the same result, return it otherwise return Bool::null.
1383 // If no mapping is possible, 'results' has less than 1305 // If no mapping is possible, 'results' has less than
1384 // (ic_data.NumberOfChecks() * 2) entries 1306 // (ic_data.NumberOfChecks() * 2) entries
1385 // An instance-of test returning all same results can be converted to a class 1307 // An instance-of test returning all same results can be converted to a class
1386 // check. 1308 // check.
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
2023 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks, 1945 new(Z) PolymorphicInstanceCallInstr(instr, unary_checks,
2024 /* with_checks = */ true, 1946 /* with_checks = */ true,
2025 /* complete = */ false); 1947 /* complete = */ false);
2026 instr->ReplaceWith(call, current_iterator()); 1948 instr->ReplaceWith(call, current_iterator());
2027 return; 1949 return;
2028 } 1950 }
2029 } 1951 }
2030 1952
2031 1953
2032 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) { 1954 void AotOptimizer::VisitStaticCall(StaticCallInstr* call) {
2033 if (!CanUnboxDouble()) { 1955 if (!IsAllowedForInlining(call->deopt_id())) {
1956 // Inlining disabled after a speculative inlining attempt.
2034 return; 1957 return;
2035 } 1958 }
2036 MethodRecognizer::Kind recognized_kind = 1959 MethodRecognizer::Kind recognized_kind =
2037 MethodRecognizer::RecognizeKind(call->function()); 1960 MethodRecognizer::RecognizeKind(call->function());
2038 MathUnaryInstr::MathUnaryKind unary_kind;
2039 switch (recognized_kind) { 1961 switch (recognized_kind) {
2040 case MethodRecognizer::kMathSqrt: 1962 case MethodRecognizer::kObjectConstructor:
2041 unary_kind = MathUnaryInstr::kSqrt; 1963 case MethodRecognizer::kObjectArrayAllocate:
2042 break;
2043 case MethodRecognizer::kMathSin:
2044 unary_kind = MathUnaryInstr::kSin;
2045 break;
2046 case MethodRecognizer::kMathCos:
2047 unary_kind = MathUnaryInstr::kCos;
2048 break;
2049 default:
2050 unary_kind = MathUnaryInstr::kIllegal;
2051 break;
2052 }
2053 if (unary_kind != MathUnaryInstr::kIllegal) {
2054 ASSERT(FLAG_precompiled_mode);
2055 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well.
2056 return;
2057 }
2058
2059 switch (recognized_kind) {
2060 case MethodRecognizer::kFloat32x4Zero: 1964 case MethodRecognizer::kFloat32x4Zero:
2061 case MethodRecognizer::kFloat32x4Splat: 1965 case MethodRecognizer::kFloat32x4Splat:
2062 case MethodRecognizer::kFloat32x4Constructor: 1966 case MethodRecognizer::kFloat32x4Constructor:
2063 case MethodRecognizer::kFloat32x4FromFloat64x2: 1967 case MethodRecognizer::kFloat32x4FromFloat64x2:
2064 case MethodRecognizer::kFloat64x2Constructor: 1968 case MethodRecognizer::kFloat64x2Constructor:
2065 case MethodRecognizer::kFloat64x2Zero: 1969 case MethodRecognizer::kFloat64x2Zero:
2066 case MethodRecognizer::kFloat64x2Splat: 1970 case MethodRecognizer::kFloat64x2Splat:
2067 case MethodRecognizer::kFloat64x2FromFloat32x4: 1971 case MethodRecognizer::kFloat64x2FromFloat32x4:
2068 case MethodRecognizer::kInt32x4BoolConstructor: 1972 case MethodRecognizer::kInt32x4BoolConstructor:
2069 case MethodRecognizer::kInt32x4Constructor: 1973 case MethodRecognizer::kInt32x4Constructor:
2070 if (!ShouldInlineSimd() || !IsAllowedForInlining(call->deopt_id())) { 1974 case MethodRecognizer::kMathSqrt:
2071 return; 1975 case MethodRecognizer::kMathDoublePow:
2072 } 1976 case MethodRecognizer::kMathSin:
1977 case MethodRecognizer::kMathCos:
1978 case MethodRecognizer::kMathTan:
1979 case MethodRecognizer::kMathAsin:
1980 case MethodRecognizer::kMathAcos:
1981 case MethodRecognizer::kMathAtan:
1982 case MethodRecognizer::kMathAtan2:
2073 FlowGraphInliner::TryReplaceStaticCallWithInline( 1983 FlowGraphInliner::TryReplaceStaticCallWithInline(
2074 flow_graph_, current_iterator(), call); 1984 flow_graph_, current_iterator(), call);
2075 break; 1985 break;
2076 case MethodRecognizer::kObjectConstructor: {
2077 // Remove the original push arguments.
2078 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2079 PushArgumentInstr* push = call->PushArgumentAt(i);
2080 push->ReplaceUsesWith(push->value()->definition());
2081 push->RemoveFromGraph();
2082 }
2083 // Manually replace call with global null constant. ReplaceCall can't
2084 // be used for definitions that are already in the graph.
2085 call->ReplaceUsesWith(flow_graph_->constant_null());
2086 ASSERT(current_iterator()->Current() == call);
2087 current_iterator()->RemoveCurrentFromGraph();
2088 break;
2089 }
2090 case MethodRecognizer::kMathMin: 1986 case MethodRecognizer::kMathMin:
2091 case MethodRecognizer::kMathMax: { 1987 case MethodRecognizer::kMathMax: {
2092 // We can handle only monomorphic min/max call sites with both arguments 1988 // We can handle only monomorphic min/max call sites with both arguments
2093 // being either doubles or smis. 1989 // being either doubles or smis.
2094 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { 1990 if (CanUnboxDouble() &&
1991 call->HasICData() &&
1992 (call->ic_data()->NumberOfChecks() == 1)) {
2095 const ICData& ic_data = *call->ic_data(); 1993 const ICData& ic_data = *call->ic_data();
2096 intptr_t result_cid = kIllegalCid; 1994 intptr_t result_cid = kIllegalCid;
2097 if (ICDataHasReceiverArgumentClassIds(ic_data, 1995 if (ICDataHasReceiverArgumentClassIds(ic_data,
2098 kDoubleCid, kDoubleCid)) { 1996 kDoubleCid, kDoubleCid)) {
2099 result_cid = kDoubleCid; 1997 result_cid = kDoubleCid;
2100 } else if (ICDataHasReceiverArgumentClassIds(ic_data, 1998 } else if (ICDataHasReceiverArgumentClassIds(ic_data,
2101 kSmiCid, kSmiCid)) { 1999 kSmiCid, kSmiCid)) {
2102 result_cid = kSmiCid; 2000 result_cid = kSmiCid;
2103 } 2001 }
2104 if (result_cid != kIllegalCid) { 2002 if (result_cid != kIllegalCid) {
(...skipping 13 matching lines...) Expand all
2118 AddCheckClass(min_max->right()->definition(), 2016 AddCheckClass(min_max->right()->definition(),
2119 unary_checks, 2017 unary_checks,
2120 call->deopt_id(), 2018 call->deopt_id(),
2121 call->env(), 2019 call->env(),
2122 call); 2020 call);
2123 ReplaceCall(call, min_max); 2021 ReplaceCall(call, min_max);
2124 } 2022 }
2125 } 2023 }
2126 break; 2024 break;
2127 } 2025 }
2128 case MethodRecognizer::kMathDoublePow:
2129 case MethodRecognizer::kMathTan:
2130 case MethodRecognizer::kMathAsin:
2131 case MethodRecognizer::kMathAcos:
2132 case MethodRecognizer::kMathAtan:
2133 case MethodRecognizer::kMathAtan2: {
2134 ASSERT(FLAG_precompiled_mode);
2135 // No UnboxDouble instructions allowed.
2136 return;
2137 }
2138 case MethodRecognizer::kDoubleFromInteger: { 2026 case MethodRecognizer::kDoubleFromInteger: {
2139 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) { 2027 if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
2140 const ICData& ic_data = *call->ic_data(); 2028 const ICData& ic_data = *call->ic_data();
2141 if (CanUnboxDouble()) { 2029 if (CanUnboxDouble()) {
2142 if (ArgIsAlways(kSmiCid, ic_data, 1)) { 2030 if (ArgIsAlways(kSmiCid, ic_data, 1)) {
2143 Definition* arg = call->ArgumentAt(1); 2031 Definition* arg = call->ArgumentAt(1);
2144 AddCheckSmi(arg, call->deopt_id(), call->env(), call); 2032 AddCheckSmi(arg, call->deopt_id(), call->env(), call);
2145 ReplaceCall(call, 2033 ReplaceCall(call,
2146 new(Z) SmiToDoubleInstr(new(Z) Value(arg), 2034 new(Z) SmiToDoubleInstr(new(Z) Value(arg),
2147 call->token_pos())); 2035 call->token_pos()));
2148 } else if (ArgIsAlways(kMintCid, ic_data, 1) && 2036 } else if (ArgIsAlways(kMintCid, ic_data, 1) &&
2149 CanConvertUnboxedMintToDouble()) { 2037 CanConvertUnboxedMintToDouble()) {
2150 Definition* arg = call->ArgumentAt(1); 2038 Definition* arg = call->ArgumentAt(1);
2151 ReplaceCall(call, 2039 ReplaceCall(call,
2152 new(Z) MintToDoubleInstr(new(Z) Value(arg), 2040 new(Z) MintToDoubleInstr(new(Z) Value(arg),
2153 call->deopt_id())); 2041 call->deopt_id()));
2154 } 2042 }
2155 } 2043 }
2156 } 2044 }
2157 break; 2045 break;
2158 } 2046 }
2159 default: { 2047 default:
2160 if (call->function().IsFactory()) { 2048 break;
2161 const Class& function_class =
2162 Class::Handle(Z, call->function().Owner());
2163 if ((function_class.library() == Library::CoreLibrary()) ||
2164 (function_class.library() == Library::TypedDataLibrary())) {
2165 intptr_t cid = FactoryRecognizer::ResultCid(call->function());
2166 switch (cid) {
2167 case kArrayCid: {
2168 Value* type = new(Z) Value(call->ArgumentAt(0));
2169 Value* num_elements = new(Z) Value(call->ArgumentAt(1));
2170 if (num_elements->BindsToConstant() &&
2171 num_elements->BoundConstant().IsSmi()) {
2172 intptr_t length =
2173 Smi::Cast(num_elements->BoundConstant()).Value();
2174 if (length >= 0 && length <= Array::kMaxElements) {
2175 CreateArrayInstr* create_array =
2176 new(Z) CreateArrayInstr(
2177 call->token_pos(), type, num_elements);
2178 ReplaceCall(call, create_array);
2179 }
2180 }
2181 }
2182 default:
2183 break;
2184 }
2185 }
2186 }
2187 }
2188 } 2049 }
2189 } 2050 }
2190 2051
2191 2052
2192 void AotOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { 2053 void AotOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) {
2193 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. 2054 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized.
2194 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) 2055 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
2195 if (!instr->can_pack_into_smi()) 2056 if (!instr->can_pack_into_smi())
2196 instr->set_representation(kUnboxedMint); 2057 instr->set_representation(kUnboxedMint);
2197 #endif 2058 #endif
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2272 flow_graph_->InsertBefore(check, new_check, 2133 flow_graph_->InsertBefore(check, new_check,
2273 check->env(), FlowGraph::kEffect); 2134 check->env(), FlowGraph::kEffect);
2274 current_iterator()->RemoveCurrentFromGraph(); 2135 current_iterator()->RemoveCurrentFromGraph();
2275 } 2136 }
2276 } 2137 }
2277 } 2138 }
2278 } 2139 }
2279 2140
2280 2141
2281 } // namespace dart 2142 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698