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

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

Issue 2254053002: Move inlining of recognized SIMD methods to the flow-graph inliner. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: addressed comment Created 4 years, 4 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 | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/flow_graph_inliner.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 1314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 for (Value::Iterator it(load->input_use_list()); 1325 for (Value::Iterator it(load->input_use_list());
1326 !it.Done(); 1326 !it.Done();
1327 it.Advance()) { 1327 it.Advance()) {
1328 it.Current()->SetReachingType(NULL); 1328 it.Current()->SetReachingType(NULL);
1329 } 1329 }
1330 } 1330 }
1331 return true; 1331 return true;
1332 } 1332 }
1333 1333
1334 1334
1335 bool AotOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
1336 MethodRecognizer::Kind getter) {
1337 if (!ShouldInlineSimd()) {
1338 return false;
1339 }
1340 AddCheckClass(call->ArgumentAt(0),
1341 ICData::ZoneHandle(
1342 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1343 call->deopt_id(),
1344 call->env(),
1345 call);
1346 intptr_t mask = 0;
1347 if ((getter == MethodRecognizer::kFloat32x4Shuffle) ||
1348 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) {
1349 // Extract shuffle mask.
1350 Definition* mask_definition = NULL;
1351 if (getter == MethodRecognizer::kFloat32x4Shuffle) {
1352 ASSERT(call->ArgumentCount() == 2);
1353 mask_definition = call->ArgumentAt(1);
1354 } else {
1355 ASSERT(getter == MethodRecognizer::kFloat32x4ShuffleMix);
1356 ASSERT(call->ArgumentCount() == 3);
1357 mask_definition = call->ArgumentAt(2);
1358 }
1359 if (!mask_definition->IsConstant()) {
1360 return false;
1361 }
1362 ASSERT(mask_definition->IsConstant());
1363 ConstantInstr* constant_instruction = mask_definition->AsConstant();
1364 const Object& constant_mask = constant_instruction->value();
1365 if (!constant_mask.IsSmi()) {
1366 return false;
1367 }
1368 ASSERT(constant_mask.IsSmi());
1369 mask = Smi::Cast(constant_mask).Value();
1370 if ((mask < 0) || (mask > 255)) {
1371 // Not a valid mask.
1372 return false;
1373 }
1374 }
1375 if (getter == MethodRecognizer::kFloat32x4GetSignMask) {
1376 Simd32x4GetSignMaskInstr* instr = new(Z) Simd32x4GetSignMaskInstr(
1377 getter,
1378 new(Z) Value(call->ArgumentAt(0)),
1379 call->deopt_id());
1380 ReplaceCall(call, instr);
1381 return true;
1382 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) {
1383 Simd32x4ShuffleMixInstr* instr = new(Z) Simd32x4ShuffleMixInstr(
1384 getter,
1385 new(Z) Value(call->ArgumentAt(0)),
1386 new(Z) Value(call->ArgumentAt(1)),
1387 mask,
1388 call->deopt_id());
1389 ReplaceCall(call, instr);
1390 return true;
1391 } else {
1392 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) ||
1393 (getter == MethodRecognizer::kFloat32x4ShuffleX) ||
1394 (getter == MethodRecognizer::kFloat32x4ShuffleY) ||
1395 (getter == MethodRecognizer::kFloat32x4ShuffleZ) ||
1396 (getter == MethodRecognizer::kFloat32x4ShuffleW));
1397 Simd32x4ShuffleInstr* instr = new(Z) Simd32x4ShuffleInstr(
1398 getter,
1399 new(Z) Value(call->ArgumentAt(0)),
1400 mask,
1401 call->deopt_id());
1402 ReplaceCall(call, instr);
1403 return true;
1404 }
1405 UNREACHABLE();
1406 return false;
1407 }
1408
1409
1410 bool AotOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call,
1411 MethodRecognizer::Kind getter) {
1412 if (!ShouldInlineSimd()) {
1413 return false;
1414 }
1415 AddCheckClass(call->ArgumentAt(0),
1416 ICData::ZoneHandle(
1417 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1418 call->deopt_id(),
1419 call->env(),
1420 call);
1421 if ((getter == MethodRecognizer::kFloat64x2GetX) ||
1422 (getter == MethodRecognizer::kFloat64x2GetY)) {
1423 Simd64x2ShuffleInstr* instr = new(Z) Simd64x2ShuffleInstr(
1424 getter,
1425 new(Z) Value(call->ArgumentAt(0)),
1426 0,
1427 call->deopt_id());
1428 ReplaceCall(call, instr);
1429 return true;
1430 }
1431 UNREACHABLE();
1432 return false;
1433 }
1434
1435
1436 bool AotOptimizer::InlineInt32x4Getter(InstanceCallInstr* call,
1437 MethodRecognizer::Kind getter) {
1438 if (!ShouldInlineSimd()) {
1439 return false;
1440 }
1441 AddCheckClass(call->ArgumentAt(0),
1442 ICData::ZoneHandle(
1443 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)),
1444 call->deopt_id(),
1445 call->env(),
1446 call);
1447 intptr_t mask = 0;
1448 if ((getter == MethodRecognizer::kInt32x4Shuffle) ||
1449 (getter == MethodRecognizer::kInt32x4ShuffleMix)) {
1450 // Extract shuffle mask.
1451 Definition* mask_definition = NULL;
1452 if (getter == MethodRecognizer::kInt32x4Shuffle) {
1453 ASSERT(call->ArgumentCount() == 2);
1454 mask_definition = call->ArgumentAt(1);
1455 } else {
1456 ASSERT(getter == MethodRecognizer::kInt32x4ShuffleMix);
1457 ASSERT(call->ArgumentCount() == 3);
1458 mask_definition = call->ArgumentAt(2);
1459 }
1460 if (!mask_definition->IsConstant()) {
1461 return false;
1462 }
1463 ASSERT(mask_definition->IsConstant());
1464 ConstantInstr* constant_instruction = mask_definition->AsConstant();
1465 const Object& constant_mask = constant_instruction->value();
1466 if (!constant_mask.IsSmi()) {
1467 return false;
1468 }
1469 ASSERT(constant_mask.IsSmi());
1470 mask = Smi::Cast(constant_mask).Value();
1471 if ((mask < 0) || (mask > 255)) {
1472 // Not a valid mask.
1473 return false;
1474 }
1475 }
1476 if (getter == MethodRecognizer::kInt32x4GetSignMask) {
1477 Simd32x4GetSignMaskInstr* instr = new(Z) Simd32x4GetSignMaskInstr(
1478 getter,
1479 new(Z) Value(call->ArgumentAt(0)),
1480 call->deopt_id());
1481 ReplaceCall(call, instr);
1482 return true;
1483 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) {
1484 Simd32x4ShuffleMixInstr* instr = new(Z) Simd32x4ShuffleMixInstr(
1485 getter,
1486 new(Z) Value(call->ArgumentAt(0)),
1487 new(Z) Value(call->ArgumentAt(1)),
1488 mask,
1489 call->deopt_id());
1490 ReplaceCall(call, instr);
1491 return true;
1492 } else if (getter == MethodRecognizer::kInt32x4Shuffle) {
1493 Simd32x4ShuffleInstr* instr = new(Z) Simd32x4ShuffleInstr(
1494 getter,
1495 new(Z) Value(call->ArgumentAt(0)),
1496 mask,
1497 call->deopt_id());
1498 ReplaceCall(call, instr);
1499 return true;
1500 } else {
1501 Int32x4GetFlagInstr* instr = new(Z) Int32x4GetFlagInstr(
1502 getter,
1503 new(Z) Value(call->ArgumentAt(0)),
1504 call->deopt_id());
1505 ReplaceCall(call, instr);
1506 return true;
1507 }
1508 }
1509
1510
1511 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, 1335 bool AotOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call,
1512 Token::Kind op_kind) { 1336 Token::Kind op_kind) {
1513 if (!ShouldInlineSimd()) { 1337 if (!ShouldInlineSimd()) {
1514 return false; 1338 return false;
1515 } 1339 }
1516 ASSERT(call->ArgumentCount() == 2); 1340 ASSERT(call->ArgumentCount() == 2);
1517 Definition* left = call->ArgumentAt(0); 1341 Definition* left = call->ArgumentAt(0);
1518 Definition* right = call->ArgumentAt(1); 1342 Definition* right = call->ArgumentAt(1);
1519 // Type check left. 1343 // Type check left.
1520 AddCheckClass(left, 1344 AddCheckClass(left,
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
1790 case MethodRecognizer::kDoubleMul: 1614 case MethodRecognizer::kDoubleMul:
1791 case MethodRecognizer::kDoubleDiv: 1615 case MethodRecognizer::kDoubleDiv:
1792 return FlowGraphInliner::TryReplaceInstanceCallWithInline( 1616 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1793 flow_graph_, current_iterator(), call); 1617 flow_graph_, current_iterator(), call);
1794 default: 1618 default:
1795 // Unsupported method. 1619 // Unsupported method.
1796 return false; 1620 return false;
1797 } 1621 }
1798 } 1622 }
1799 1623
1800 if (IsSupportedByteArrayViewCid(class_ids[0])) { 1624 if (IsSupportedByteArrayViewCid(class_ids[0]) ||
1625 (class_ids[0] == kFloat32x4Cid) ||
1626 (class_ids[0] == kInt32x4Cid) ||
1627 (class_ids[0] == kFloat64x2Cid)) {
1801 return FlowGraphInliner::TryReplaceInstanceCallWithInline( 1628 return FlowGraphInliner::TryReplaceInstanceCallWithInline(
1802 flow_graph_, current_iterator(), call); 1629 flow_graph_, current_iterator(), call);
1803 } 1630 }
1804 1631
1805 if (class_ids[0] == kFloat32x4Cid) {
1806 return TryInlineFloat32x4Method(call, recognized_kind);
1807 }
1808
1809 if (class_ids[0] == kInt32x4Cid) {
1810 return TryInlineInt32x4Method(call, recognized_kind);
1811 }
1812
1813 if (class_ids[0] == kFloat64x2Cid) {
1814 return TryInlineFloat64x2Method(call, recognized_kind);
1815 }
1816
1817 return false; 1632 return false;
1818 } 1633 }
1819 1634
1820
1821 bool AotOptimizer::TryInlineFloat32x4Constructor(
1822 StaticCallInstr* call,
1823 MethodRecognizer::Kind recognized_kind) {
1824 // Cannot handle unboxed instructions.
1825 ASSERT(FLAG_precompiled_mode);
1826 return false;
1827 }
1828
1829
1830 bool AotOptimizer::TryInlineFloat64x2Constructor(
1831 StaticCallInstr* call,
1832 MethodRecognizer::Kind recognized_kind) {
1833 // Cannot handle unboxed instructions.
1834 ASSERT(FLAG_precompiled_mode);
1835 return false;
1836 }
1837
1838
1839 bool AotOptimizer::TryInlineInt32x4Constructor(
1840 StaticCallInstr* call,
1841 MethodRecognizer::Kind recognized_kind) {
1842 // Cannot handle unboxed instructions.
1843 ASSERT(FLAG_precompiled_mode);
1844 return false;
1845 }
1846
1847
1848 bool AotOptimizer::TryInlineFloat32x4Method(
1849 InstanceCallInstr* call,
1850 MethodRecognizer::Kind recognized_kind) {
1851 // Cannot handle unboxed instructions.
1852 return false;
1853 }
1854
1855
1856 bool AotOptimizer::TryInlineFloat64x2Method(
1857 InstanceCallInstr* call,
1858 MethodRecognizer::Kind recognized_kind) {
1859 // Cannot handle unboxed instructions.
1860 return false;
1861 }
1862
1863
1864 bool AotOptimizer::TryInlineInt32x4Method(
1865 InstanceCallInstr* call,
1866 MethodRecognizer::Kind recognized_kind) {
1867 // Cannot handle unboxed instructions.
1868 return false;
1869 }
1870
1871 1635
1872 // If type tests specified by 'ic_data' do not depend on type arguments, 1636 // If type tests specified by 'ic_data' do not depend on type arguments,
1873 // return mapping cid->result in 'results' (i : cid; i + 1: result). 1637 // return mapping cid->result in 'results' (i : cid; i + 1: result).
1874 // If all tests yield the same result, return it otherwise return Bool::null. 1638 // If all tests yield the same result, return it otherwise return Bool::null.
1875 // If no mapping is possible, 'results' has less than 1639 // If no mapping is possible, 'results' has less than
1876 // (ic_data.NumberOfChecks() * 2) entries 1640 // (ic_data.NumberOfChecks() * 2) entries
1877 // An instance-of test returning all same results can be converted to a class 1641 // An instance-of test returning all same results can be converted to a class
1878 // check. 1642 // check.
1879 RawBool* AotOptimizer::InstanceOfAsBool( 1643 RawBool* AotOptimizer::InstanceOfAsBool(
1880 const ICData& ic_data, 1644 const ICData& ic_data,
(...skipping 665 matching lines...) Expand 10 before | Expand all | Expand 10 after
2546 ASSERT(FLAG_precompiled_mode); 2310 ASSERT(FLAG_precompiled_mode);
2547 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well. 2311 // TODO(srdjan): Adapt MathUnaryInstr to allow tagged inputs as well.
2548 return; 2312 return;
2549 } 2313 }
2550 2314
2551 switch (recognized_kind) { 2315 switch (recognized_kind) {
2552 case MethodRecognizer::kFloat32x4Zero: 2316 case MethodRecognizer::kFloat32x4Zero:
2553 case MethodRecognizer::kFloat32x4Splat: 2317 case MethodRecognizer::kFloat32x4Splat:
2554 case MethodRecognizer::kFloat32x4Constructor: 2318 case MethodRecognizer::kFloat32x4Constructor:
2555 case MethodRecognizer::kFloat32x4FromFloat64x2: 2319 case MethodRecognizer::kFloat32x4FromFloat64x2:
2556 TryInlineFloat32x4Constructor(call, recognized_kind);
2557 break;
2558 case MethodRecognizer::kFloat64x2Constructor: 2320 case MethodRecognizer::kFloat64x2Constructor:
2559 case MethodRecognizer::kFloat64x2Zero: 2321 case MethodRecognizer::kFloat64x2Zero:
2560 case MethodRecognizer::kFloat64x2Splat: 2322 case MethodRecognizer::kFloat64x2Splat:
2561 case MethodRecognizer::kFloat64x2FromFloat32x4: 2323 case MethodRecognizer::kFloat64x2FromFloat32x4:
2562 TryInlineFloat64x2Constructor(call, recognized_kind);
2563 break;
2564 case MethodRecognizer::kInt32x4BoolConstructor: 2324 case MethodRecognizer::kInt32x4BoolConstructor:
2565 case MethodRecognizer::kInt32x4Constructor: 2325 case MethodRecognizer::kInt32x4Constructor:
2566 TryInlineInt32x4Constructor(call, recognized_kind); 2326 if (!ShouldInlineSimd() || !IsAllowedForInlining(call->deopt_id())) {
2327 return;
2328 }
2329 FlowGraphInliner::TryReplaceStaticCallWithInline(
2330 flow_graph_, current_iterator(), call);
2567 break; 2331 break;
2568 case MethodRecognizer::kObjectConstructor: { 2332 case MethodRecognizer::kObjectConstructor: {
2569 // Remove the original push arguments. 2333 // Remove the original push arguments.
2570 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 2334 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
2571 PushArgumentInstr* push = call->PushArgumentAt(i); 2335 PushArgumentInstr* push = call->PushArgumentAt(i);
2572 push->ReplaceUsesWith(push->value()->definition()); 2336 push->ReplaceUsesWith(push->value()->definition());
2573 push->RemoveFromGraph(); 2337 push->RemoveFromGraph();
2574 } 2338 }
2575 // Manually replace call with global null constant. ReplaceCall can't 2339 // Manually replace call with global null constant. ReplaceCall can't
2576 // be used for definitions that are already in the graph. 2340 // be used for definitions that are already in the graph.
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
2764 flow_graph_->InsertBefore(check, new_check, 2528 flow_graph_->InsertBefore(check, new_check,
2765 check->env(), FlowGraph::kEffect); 2529 check->env(), FlowGraph::kEffect);
2766 current_iterator()->RemoveCurrentFromGraph(); 2530 current_iterator()->RemoveCurrentFromGraph();
2767 } 2531 }
2768 } 2532 }
2769 } 2533 }
2770 } 2534 }
2771 2535
2772 2536
2773 } // namespace dart 2537 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/aot_optimizer.h ('k') | runtime/vm/flow_graph_inliner.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698