| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |