| 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/jit_optimizer.h" | 5 #include "vm/jit_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 1320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1331 for (Value::Iterator it(load->input_use_list()); | 1331 for (Value::Iterator it(load->input_use_list()); |
| 1332 !it.Done(); | 1332 !it.Done(); |
| 1333 it.Advance()) { | 1333 it.Advance()) { |
| 1334 it.Current()->SetReachingType(NULL); | 1334 it.Current()->SetReachingType(NULL); |
| 1335 } | 1335 } |
| 1336 } | 1336 } |
| 1337 return true; | 1337 return true; |
| 1338 } | 1338 } |
| 1339 | 1339 |
| 1340 | 1340 |
| 1341 bool JitOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call, | |
| 1342 MethodRecognizer::Kind getter) { | |
| 1343 if (!ShouldInlineSimd()) { | |
| 1344 return false; | |
| 1345 } | |
| 1346 AddCheckClass(call->ArgumentAt(0), | |
| 1347 ICData::ZoneHandle( | |
| 1348 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 1349 call->deopt_id(), | |
| 1350 call->env(), | |
| 1351 call); | |
| 1352 intptr_t mask = 0; | |
| 1353 if ((getter == MethodRecognizer::kFloat32x4Shuffle) || | |
| 1354 (getter == MethodRecognizer::kFloat32x4ShuffleMix)) { | |
| 1355 // Extract shuffle mask. | |
| 1356 Definition* mask_definition = NULL; | |
| 1357 if (getter == MethodRecognizer::kFloat32x4Shuffle) { | |
| 1358 ASSERT(call->ArgumentCount() == 2); | |
| 1359 mask_definition = call->ArgumentAt(1); | |
| 1360 } else { | |
| 1361 ASSERT(getter == MethodRecognizer::kFloat32x4ShuffleMix); | |
| 1362 ASSERT(call->ArgumentCount() == 3); | |
| 1363 mask_definition = call->ArgumentAt(2); | |
| 1364 } | |
| 1365 if (!mask_definition->IsConstant()) { | |
| 1366 return false; | |
| 1367 } | |
| 1368 ASSERT(mask_definition->IsConstant()); | |
| 1369 ConstantInstr* constant_instruction = mask_definition->AsConstant(); | |
| 1370 const Object& constant_mask = constant_instruction->value(); | |
| 1371 if (!constant_mask.IsSmi()) { | |
| 1372 return false; | |
| 1373 } | |
| 1374 ASSERT(constant_mask.IsSmi()); | |
| 1375 mask = Smi::Cast(constant_mask).Value(); | |
| 1376 if ((mask < 0) || (mask > 255)) { | |
| 1377 // Not a valid mask. | |
| 1378 return false; | |
| 1379 } | |
| 1380 } | |
| 1381 if (getter == MethodRecognizer::kFloat32x4GetSignMask) { | |
| 1382 Simd32x4GetSignMaskInstr* instr = new(Z) Simd32x4GetSignMaskInstr( | |
| 1383 getter, | |
| 1384 new(Z) Value(call->ArgumentAt(0)), | |
| 1385 call->deopt_id()); | |
| 1386 ReplaceCall(call, instr); | |
| 1387 return true; | |
| 1388 } else if (getter == MethodRecognizer::kFloat32x4ShuffleMix) { | |
| 1389 Simd32x4ShuffleMixInstr* instr = new(Z) Simd32x4ShuffleMixInstr( | |
| 1390 getter, | |
| 1391 new(Z) Value(call->ArgumentAt(0)), | |
| 1392 new(Z) Value(call->ArgumentAt(1)), | |
| 1393 mask, | |
| 1394 call->deopt_id()); | |
| 1395 ReplaceCall(call, instr); | |
| 1396 return true; | |
| 1397 } else { | |
| 1398 ASSERT((getter == MethodRecognizer::kFloat32x4Shuffle) || | |
| 1399 (getter == MethodRecognizer::kFloat32x4ShuffleX) || | |
| 1400 (getter == MethodRecognizer::kFloat32x4ShuffleY) || | |
| 1401 (getter == MethodRecognizer::kFloat32x4ShuffleZ) || | |
| 1402 (getter == MethodRecognizer::kFloat32x4ShuffleW)); | |
| 1403 Simd32x4ShuffleInstr* instr = new(Z) Simd32x4ShuffleInstr( | |
| 1404 getter, | |
| 1405 new(Z) Value(call->ArgumentAt(0)), | |
| 1406 mask, | |
| 1407 call->deopt_id()); | |
| 1408 ReplaceCall(call, instr); | |
| 1409 return true; | |
| 1410 } | |
| 1411 UNREACHABLE(); | |
| 1412 return false; | |
| 1413 } | |
| 1414 | |
| 1415 | |
| 1416 bool JitOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, | 1341 bool JitOptimizer::InlineFloat64x2Getter(InstanceCallInstr* call, |
| 1417 MethodRecognizer::Kind getter) { | 1342 MethodRecognizer::Kind getter) { |
| 1418 if (!ShouldInlineSimd()) { | 1343 if (!ShouldInlineSimd()) { |
| 1419 return false; | 1344 return false; |
| 1420 } | 1345 } |
| 1421 AddCheckClass(call->ArgumentAt(0), | 1346 AddCheckClass(call->ArgumentAt(0), |
| 1422 ICData::ZoneHandle( | 1347 ICData::ZoneHandle( |
| 1423 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | 1348 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), |
| 1424 call->deopt_id(), | 1349 call->deopt_id(), |
| 1425 call->env(), | 1350 call->env(), |
| 1426 call); | 1351 call); |
| 1427 if ((getter == MethodRecognizer::kFloat64x2GetX) || | 1352 if ((getter == MethodRecognizer::kFloat64x2GetX) || |
| 1428 (getter == MethodRecognizer::kFloat64x2GetY)) { | 1353 (getter == MethodRecognizer::kFloat64x2GetY)) { |
| 1429 Simd64x2ShuffleInstr* instr = new(Z) Simd64x2ShuffleInstr( | 1354 Simd64x2ShuffleInstr* instr = new(Z) Simd64x2ShuffleInstr( |
| 1430 getter, | 1355 getter, |
| 1431 new(Z) Value(call->ArgumentAt(0)), | 1356 new(Z) Value(call->ArgumentAt(0)), |
| 1432 0, | 1357 0, |
| 1433 call->deopt_id()); | 1358 call->deopt_id()); |
| 1434 ReplaceCall(call, instr); | 1359 ReplaceCall(call, instr); |
| 1435 return true; | 1360 return true; |
| 1436 } | 1361 } |
| 1437 UNREACHABLE(); | 1362 UNREACHABLE(); |
| 1438 return false; | 1363 return false; |
| 1439 } | 1364 } |
| 1440 | 1365 |
| 1441 | 1366 |
| 1442 bool JitOptimizer::InlineInt32x4Getter(InstanceCallInstr* call, | |
| 1443 MethodRecognizer::Kind getter) { | |
| 1444 if (!ShouldInlineSimd()) { | |
| 1445 return false; | |
| 1446 } | |
| 1447 AddCheckClass(call->ArgumentAt(0), | |
| 1448 ICData::ZoneHandle( | |
| 1449 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 1450 call->deopt_id(), | |
| 1451 call->env(), | |
| 1452 call); | |
| 1453 intptr_t mask = 0; | |
| 1454 if ((getter == MethodRecognizer::kInt32x4Shuffle) || | |
| 1455 (getter == MethodRecognizer::kInt32x4ShuffleMix)) { | |
| 1456 // Extract shuffle mask. | |
| 1457 Definition* mask_definition = NULL; | |
| 1458 if (getter == MethodRecognizer::kInt32x4Shuffle) { | |
| 1459 ASSERT(call->ArgumentCount() == 2); | |
| 1460 mask_definition = call->ArgumentAt(1); | |
| 1461 } else { | |
| 1462 ASSERT(getter == MethodRecognizer::kInt32x4ShuffleMix); | |
| 1463 ASSERT(call->ArgumentCount() == 3); | |
| 1464 mask_definition = call->ArgumentAt(2); | |
| 1465 } | |
| 1466 if (!mask_definition->IsConstant()) { | |
| 1467 return false; | |
| 1468 } | |
| 1469 ASSERT(mask_definition->IsConstant()); | |
| 1470 ConstantInstr* constant_instruction = mask_definition->AsConstant(); | |
| 1471 const Object& constant_mask = constant_instruction->value(); | |
| 1472 if (!constant_mask.IsSmi()) { | |
| 1473 return false; | |
| 1474 } | |
| 1475 ASSERT(constant_mask.IsSmi()); | |
| 1476 mask = Smi::Cast(constant_mask).Value(); | |
| 1477 if ((mask < 0) || (mask > 255)) { | |
| 1478 // Not a valid mask. | |
| 1479 return false; | |
| 1480 } | |
| 1481 } | |
| 1482 if (getter == MethodRecognizer::kInt32x4GetSignMask) { | |
| 1483 Simd32x4GetSignMaskInstr* instr = new(Z) Simd32x4GetSignMaskInstr( | |
| 1484 getter, | |
| 1485 new(Z) Value(call->ArgumentAt(0)), | |
| 1486 call->deopt_id()); | |
| 1487 ReplaceCall(call, instr); | |
| 1488 return true; | |
| 1489 } else if (getter == MethodRecognizer::kInt32x4ShuffleMix) { | |
| 1490 Simd32x4ShuffleMixInstr* instr = new(Z) Simd32x4ShuffleMixInstr( | |
| 1491 getter, | |
| 1492 new(Z) Value(call->ArgumentAt(0)), | |
| 1493 new(Z) Value(call->ArgumentAt(1)), | |
| 1494 mask, | |
| 1495 call->deopt_id()); | |
| 1496 ReplaceCall(call, instr); | |
| 1497 return true; | |
| 1498 } else if (getter == MethodRecognizer::kInt32x4Shuffle) { | |
| 1499 Simd32x4ShuffleInstr* instr = new(Z) Simd32x4ShuffleInstr( | |
| 1500 getter, | |
| 1501 new(Z) Value(call->ArgumentAt(0)), | |
| 1502 mask, | |
| 1503 call->deopt_id()); | |
| 1504 ReplaceCall(call, instr); | |
| 1505 return true; | |
| 1506 } else { | |
| 1507 Int32x4GetFlagInstr* instr = new(Z) Int32x4GetFlagInstr( | |
| 1508 getter, | |
| 1509 new(Z) Value(call->ArgumentAt(0)), | |
| 1510 call->deopt_id()); | |
| 1511 ReplaceCall(call, instr); | |
| 1512 return true; | |
| 1513 } | |
| 1514 } | |
| 1515 | |
| 1516 | |
| 1517 bool JitOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, | 1367 bool JitOptimizer::InlineFloat32x4BinaryOp(InstanceCallInstr* call, |
| 1518 Token::Kind op_kind) { | 1368 Token::Kind op_kind) { |
| 1519 if (!ShouldInlineSimd()) { | 1369 if (!ShouldInlineSimd()) { |
| 1520 return false; | 1370 return false; |
| 1521 } | 1371 } |
| 1522 ASSERT(call->ArgumentCount() == 2); | 1372 ASSERT(call->ArgumentCount() == 2); |
| 1523 Definition* left = call->ArgumentAt(0); | 1373 Definition* left = call->ArgumentAt(0); |
| 1524 Definition* right = call->ArgumentAt(1); | 1374 Definition* right = call->ArgumentAt(1); |
| 1525 // Type check left. | 1375 // Type check left. |
| 1526 AddCheckClass(left, | 1376 AddCheckClass(left, |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1796 case MethodRecognizer::kDoubleMul: | 1646 case MethodRecognizer::kDoubleMul: |
| 1797 case MethodRecognizer::kDoubleDiv: | 1647 case MethodRecognizer::kDoubleDiv: |
| 1798 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | 1648 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1799 flow_graph_, current_iterator(), call); | 1649 flow_graph_, current_iterator(), call); |
| 1800 default: | 1650 default: |
| 1801 // Unsupported method. | 1651 // Unsupported method. |
| 1802 return false; | 1652 return false; |
| 1803 } | 1653 } |
| 1804 } | 1654 } |
| 1805 | 1655 |
| 1806 if (IsSupportedByteArrayViewCid(class_ids[0])) { | 1656 if (IsSupportedByteArrayViewCid(class_ids[0]) || |
| 1657 (class_ids[0] == kFloat32x4Cid) || |
| 1658 (class_ids[0] == kInt32x4Cid) || |
| 1659 (class_ids[0] == kFloat64x2Cid)) { |
| 1807 return FlowGraphInliner::TryReplaceInstanceCallWithInline( | 1660 return FlowGraphInliner::TryReplaceInstanceCallWithInline( |
| 1808 flow_graph_, current_iterator(), call); | 1661 flow_graph_, current_iterator(), call); |
| 1809 } | 1662 } |
| 1810 | 1663 |
| 1811 if (class_ids[0] == kFloat32x4Cid) { | |
| 1812 return TryInlineFloat32x4Method(call, recognized_kind); | |
| 1813 } | |
| 1814 | |
| 1815 if (class_ids[0] == kInt32x4Cid) { | |
| 1816 return TryInlineInt32x4Method(call, recognized_kind); | |
| 1817 } | |
| 1818 | |
| 1819 if (class_ids[0] == kFloat64x2Cid) { | |
| 1820 return TryInlineFloat64x2Method(call, recognized_kind); | |
| 1821 } | |
| 1822 | |
| 1823 return false; | 1664 return false; |
| 1824 } | 1665 } |
| 1825 | 1666 |
| 1826 | 1667 |
| 1827 bool JitOptimizer::TryInlineFloat32x4Constructor( | |
| 1828 StaticCallInstr* call, | |
| 1829 MethodRecognizer::Kind recognized_kind) { | |
| 1830 if (!ShouldInlineSimd()) { | |
| 1831 return false; | |
| 1832 } | |
| 1833 if (recognized_kind == MethodRecognizer::kFloat32x4Zero) { | |
| 1834 Float32x4ZeroInstr* zero = new(Z) Float32x4ZeroInstr(); | |
| 1835 ReplaceCall(call, zero); | |
| 1836 return true; | |
| 1837 } else if (recognized_kind == MethodRecognizer::kFloat32x4Splat) { | |
| 1838 Float32x4SplatInstr* splat = | |
| 1839 new(Z) Float32x4SplatInstr( | |
| 1840 new(Z) Value(call->ArgumentAt(1)), call->deopt_id()); | |
| 1841 ReplaceCall(call, splat); | |
| 1842 return true; | |
| 1843 } else if (recognized_kind == MethodRecognizer::kFloat32x4Constructor) { | |
| 1844 Float32x4ConstructorInstr* con = | |
| 1845 new(Z) Float32x4ConstructorInstr( | |
| 1846 new(Z) Value(call->ArgumentAt(1)), | |
| 1847 new(Z) Value(call->ArgumentAt(2)), | |
| 1848 new(Z) Value(call->ArgumentAt(3)), | |
| 1849 new(Z) Value(call->ArgumentAt(4)), | |
| 1850 call->deopt_id()); | |
| 1851 ReplaceCall(call, con); | |
| 1852 return true; | |
| 1853 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromInt32x4Bits) { | |
| 1854 Int32x4ToFloat32x4Instr* cast = | |
| 1855 new(Z) Int32x4ToFloat32x4Instr( | |
| 1856 new(Z) Value(call->ArgumentAt(1)), call->deopt_id()); | |
| 1857 ReplaceCall(call, cast); | |
| 1858 return true; | |
| 1859 } else if (recognized_kind == MethodRecognizer::kFloat32x4FromFloat64x2) { | |
| 1860 Float64x2ToFloat32x4Instr* cast = | |
| 1861 new(Z) Float64x2ToFloat32x4Instr( | |
| 1862 new(Z) Value(call->ArgumentAt(1)), call->deopt_id()); | |
| 1863 ReplaceCall(call, cast); | |
| 1864 return true; | |
| 1865 } | |
| 1866 return false; | |
| 1867 } | |
| 1868 | |
| 1869 | |
| 1870 bool JitOptimizer::TryInlineFloat64x2Constructor( | |
| 1871 StaticCallInstr* call, | |
| 1872 MethodRecognizer::Kind recognized_kind) { | |
| 1873 if (!ShouldInlineSimd()) { | |
| 1874 return false; | |
| 1875 } | |
| 1876 if (recognized_kind == MethodRecognizer::kFloat64x2Zero) { | |
| 1877 Float64x2ZeroInstr* zero = new(Z) Float64x2ZeroInstr(); | |
| 1878 ReplaceCall(call, zero); | |
| 1879 return true; | |
| 1880 } else if (recognized_kind == MethodRecognizer::kFloat64x2Splat) { | |
| 1881 Float64x2SplatInstr* splat = | |
| 1882 new(Z) Float64x2SplatInstr( | |
| 1883 new(Z) Value(call->ArgumentAt(1)), call->deopt_id()); | |
| 1884 ReplaceCall(call, splat); | |
| 1885 return true; | |
| 1886 } else if (recognized_kind == MethodRecognizer::kFloat64x2Constructor) { | |
| 1887 Float64x2ConstructorInstr* con = | |
| 1888 new(Z) Float64x2ConstructorInstr( | |
| 1889 new(Z) Value(call->ArgumentAt(1)), | |
| 1890 new(Z) Value(call->ArgumentAt(2)), | |
| 1891 call->deopt_id()); | |
| 1892 ReplaceCall(call, con); | |
| 1893 return true; | |
| 1894 } else if (recognized_kind == MethodRecognizer::kFloat64x2FromFloat32x4) { | |
| 1895 Float32x4ToFloat64x2Instr* cast = | |
| 1896 new(Z) Float32x4ToFloat64x2Instr( | |
| 1897 new(Z) Value(call->ArgumentAt(1)), call->deopt_id()); | |
| 1898 ReplaceCall(call, cast); | |
| 1899 return true; | |
| 1900 } | |
| 1901 return false; | |
| 1902 } | |
| 1903 | |
| 1904 | |
| 1905 bool JitOptimizer::TryInlineInt32x4Constructor( | |
| 1906 StaticCallInstr* call, | |
| 1907 MethodRecognizer::Kind recognized_kind) { | |
| 1908 if (!ShouldInlineSimd()) { | |
| 1909 return false; | |
| 1910 } | |
| 1911 if (recognized_kind == MethodRecognizer::kInt32x4BoolConstructor) { | |
| 1912 Int32x4BoolConstructorInstr* con = | |
| 1913 new(Z) Int32x4BoolConstructorInstr( | |
| 1914 new(Z) Value(call->ArgumentAt(1)), | |
| 1915 new(Z) Value(call->ArgumentAt(2)), | |
| 1916 new(Z) Value(call->ArgumentAt(3)), | |
| 1917 new(Z) Value(call->ArgumentAt(4)), | |
| 1918 call->deopt_id()); | |
| 1919 ReplaceCall(call, con); | |
| 1920 return true; | |
| 1921 } else if (recognized_kind == MethodRecognizer::kInt32x4FromFloat32x4Bits) { | |
| 1922 Float32x4ToInt32x4Instr* cast = | |
| 1923 new(Z) Float32x4ToInt32x4Instr( | |
| 1924 new(Z) Value(call->ArgumentAt(1)), call->deopt_id()); | |
| 1925 ReplaceCall(call, cast); | |
| 1926 return true; | |
| 1927 } else if (recognized_kind == MethodRecognizer::kInt32x4Constructor) { | |
| 1928 Int32x4ConstructorInstr* con = | |
| 1929 new(Z) Int32x4ConstructorInstr( | |
| 1930 new(Z) Value(call->ArgumentAt(1)), | |
| 1931 new(Z) Value(call->ArgumentAt(2)), | |
| 1932 new(Z) Value(call->ArgumentAt(3)), | |
| 1933 new(Z) Value(call->ArgumentAt(4)), | |
| 1934 call->deopt_id()); | |
| 1935 ReplaceCall(call, con); | |
| 1936 return true; | |
| 1937 } | |
| 1938 return false; | |
| 1939 } | |
| 1940 | |
| 1941 | |
| 1942 bool JitOptimizer::TryInlineFloat32x4Method( | |
| 1943 InstanceCallInstr* call, | |
| 1944 MethodRecognizer::Kind recognized_kind) { | |
| 1945 if (!ShouldInlineSimd()) { | |
| 1946 return false; | |
| 1947 } | |
| 1948 ASSERT(call->HasICData()); | |
| 1949 switch (recognized_kind) { | |
| 1950 case MethodRecognizer::kFloat32x4ShuffleX: | |
| 1951 case MethodRecognizer::kFloat32x4ShuffleY: | |
| 1952 case MethodRecognizer::kFloat32x4ShuffleZ: | |
| 1953 case MethodRecognizer::kFloat32x4ShuffleW: | |
| 1954 case MethodRecognizer::kFloat32x4GetSignMask: | |
| 1955 ASSERT(call->ic_data()->HasReceiverClassId(kFloat32x4Cid)); | |
| 1956 ASSERT(call->ic_data()->HasOneTarget()); | |
| 1957 return InlineFloat32x4Getter(call, recognized_kind); | |
| 1958 | |
| 1959 case MethodRecognizer::kFloat32x4Equal: | |
| 1960 case MethodRecognizer::kFloat32x4GreaterThan: | |
| 1961 case MethodRecognizer::kFloat32x4GreaterThanOrEqual: | |
| 1962 case MethodRecognizer::kFloat32x4LessThan: | |
| 1963 case MethodRecognizer::kFloat32x4LessThanOrEqual: | |
| 1964 case MethodRecognizer::kFloat32x4NotEqual: { | |
| 1965 Definition* left = call->ArgumentAt(0); | |
| 1966 Definition* right = call->ArgumentAt(1); | |
| 1967 Float32x4ComparisonInstr* cmp = | |
| 1968 new(Z) Float32x4ComparisonInstr(recognized_kind, | |
| 1969 new(Z) Value(left), | |
| 1970 new(Z) Value(right), | |
| 1971 call->deopt_id()); | |
| 1972 ReplaceCall(call, cmp); | |
| 1973 return true; | |
| 1974 } | |
| 1975 case MethodRecognizer::kFloat32x4Min: | |
| 1976 case MethodRecognizer::kFloat32x4Max: { | |
| 1977 Definition* left = call->ArgumentAt(0); | |
| 1978 Definition* right = call->ArgumentAt(1); | |
| 1979 Float32x4MinMaxInstr* minmax = | |
| 1980 new(Z) Float32x4MinMaxInstr( | |
| 1981 recognized_kind, | |
| 1982 new(Z) Value(left), | |
| 1983 new(Z) Value(right), | |
| 1984 call->deopt_id()); | |
| 1985 ReplaceCall(call, minmax); | |
| 1986 return true; | |
| 1987 } | |
| 1988 case MethodRecognizer::kFloat32x4Scale: { | |
| 1989 Definition* left = call->ArgumentAt(0); | |
| 1990 Definition* right = call->ArgumentAt(1); | |
| 1991 // Left and right values are swapped when handed to the instruction, | |
| 1992 // this is done so that the double value is loaded into the output | |
| 1993 // register and can be destroyed. | |
| 1994 Float32x4ScaleInstr* scale = | |
| 1995 new(Z) Float32x4ScaleInstr(recognized_kind, | |
| 1996 new(Z) Value(right), | |
| 1997 new(Z) Value(left), | |
| 1998 call->deopt_id()); | |
| 1999 ReplaceCall(call, scale); | |
| 2000 return true; | |
| 2001 } | |
| 2002 case MethodRecognizer::kFloat32x4Sqrt: | |
| 2003 case MethodRecognizer::kFloat32x4ReciprocalSqrt: | |
| 2004 case MethodRecognizer::kFloat32x4Reciprocal: { | |
| 2005 Definition* left = call->ArgumentAt(0); | |
| 2006 Float32x4SqrtInstr* sqrt = | |
| 2007 new(Z) Float32x4SqrtInstr(recognized_kind, | |
| 2008 new(Z) Value(left), | |
| 2009 call->deopt_id()); | |
| 2010 ReplaceCall(call, sqrt); | |
| 2011 return true; | |
| 2012 } | |
| 2013 case MethodRecognizer::kFloat32x4WithX: | |
| 2014 case MethodRecognizer::kFloat32x4WithY: | |
| 2015 case MethodRecognizer::kFloat32x4WithZ: | |
| 2016 case MethodRecognizer::kFloat32x4WithW: { | |
| 2017 Definition* left = call->ArgumentAt(0); | |
| 2018 Definition* right = call->ArgumentAt(1); | |
| 2019 Float32x4WithInstr* with = new(Z) Float32x4WithInstr(recognized_kind, | |
| 2020 new(Z) Value(left), | |
| 2021 new(Z) Value(right), | |
| 2022 call->deopt_id()); | |
| 2023 ReplaceCall(call, with); | |
| 2024 return true; | |
| 2025 } | |
| 2026 case MethodRecognizer::kFloat32x4Absolute: | |
| 2027 case MethodRecognizer::kFloat32x4Negate: { | |
| 2028 Definition* left = call->ArgumentAt(0); | |
| 2029 Float32x4ZeroArgInstr* zeroArg = | |
| 2030 new(Z) Float32x4ZeroArgInstr( | |
| 2031 recognized_kind, new(Z) Value(left), call->deopt_id()); | |
| 2032 ReplaceCall(call, zeroArg); | |
| 2033 return true; | |
| 2034 } | |
| 2035 case MethodRecognizer::kFloat32x4Clamp: { | |
| 2036 Definition* left = call->ArgumentAt(0); | |
| 2037 Definition* lower = call->ArgumentAt(1); | |
| 2038 Definition* upper = call->ArgumentAt(2); | |
| 2039 Float32x4ClampInstr* clamp = new(Z) Float32x4ClampInstr( | |
| 2040 new(Z) Value(left), | |
| 2041 new(Z) Value(lower), | |
| 2042 new(Z) Value(upper), | |
| 2043 call->deopt_id()); | |
| 2044 ReplaceCall(call, clamp); | |
| 2045 return true; | |
| 2046 } | |
| 2047 case MethodRecognizer::kFloat32x4ShuffleMix: | |
| 2048 case MethodRecognizer::kFloat32x4Shuffle: { | |
| 2049 return InlineFloat32x4Getter(call, recognized_kind); | |
| 2050 } | |
| 2051 default: | |
| 2052 return false; | |
| 2053 } | |
| 2054 } | |
| 2055 | |
| 2056 | |
| 2057 bool JitOptimizer::TryInlineFloat64x2Method( | |
| 2058 InstanceCallInstr* call, | |
| 2059 MethodRecognizer::Kind recognized_kind) { | |
| 2060 if (!ShouldInlineSimd()) { | |
| 2061 return false; | |
| 2062 } | |
| 2063 ASSERT(call->HasICData()); | |
| 2064 switch (recognized_kind) { | |
| 2065 case MethodRecognizer::kFloat64x2GetX: | |
| 2066 case MethodRecognizer::kFloat64x2GetY: | |
| 2067 ASSERT(call->ic_data()->HasReceiverClassId(kFloat64x2Cid)); | |
| 2068 ASSERT(call->ic_data()->HasOneTarget()); | |
| 2069 return InlineFloat64x2Getter(call, recognized_kind); | |
| 2070 case MethodRecognizer::kFloat64x2Negate: | |
| 2071 case MethodRecognizer::kFloat64x2Abs: | |
| 2072 case MethodRecognizer::kFloat64x2Sqrt: | |
| 2073 case MethodRecognizer::kFloat64x2GetSignMask: { | |
| 2074 Definition* left = call->ArgumentAt(0); | |
| 2075 Float64x2ZeroArgInstr* zeroArg = | |
| 2076 new(Z) Float64x2ZeroArgInstr( | |
| 2077 recognized_kind, new(Z) Value(left), call->deopt_id()); | |
| 2078 ReplaceCall(call, zeroArg); | |
| 2079 return true; | |
| 2080 } | |
| 2081 case MethodRecognizer::kFloat64x2Scale: | |
| 2082 case MethodRecognizer::kFloat64x2WithX: | |
| 2083 case MethodRecognizer::kFloat64x2WithY: | |
| 2084 case MethodRecognizer::kFloat64x2Min: | |
| 2085 case MethodRecognizer::kFloat64x2Max: { | |
| 2086 Definition* left = call->ArgumentAt(0); | |
| 2087 Definition* right = call->ArgumentAt(1); | |
| 2088 Float64x2OneArgInstr* zeroArg = | |
| 2089 new(Z) Float64x2OneArgInstr(recognized_kind, | |
| 2090 new(Z) Value(left), | |
| 2091 new(Z) Value(right), | |
| 2092 call->deopt_id()); | |
| 2093 ReplaceCall(call, zeroArg); | |
| 2094 return true; | |
| 2095 } | |
| 2096 default: | |
| 2097 return false; | |
| 2098 } | |
| 2099 } | |
| 2100 | |
| 2101 | |
| 2102 bool JitOptimizer::TryInlineInt32x4Method( | |
| 2103 InstanceCallInstr* call, | |
| 2104 MethodRecognizer::Kind recognized_kind) { | |
| 2105 if (!ShouldInlineSimd()) { | |
| 2106 return false; | |
| 2107 } | |
| 2108 ASSERT(call->HasICData()); | |
| 2109 switch (recognized_kind) { | |
| 2110 case MethodRecognizer::kInt32x4ShuffleMix: | |
| 2111 case MethodRecognizer::kInt32x4Shuffle: | |
| 2112 case MethodRecognizer::kInt32x4GetFlagX: | |
| 2113 case MethodRecognizer::kInt32x4GetFlagY: | |
| 2114 case MethodRecognizer::kInt32x4GetFlagZ: | |
| 2115 case MethodRecognizer::kInt32x4GetFlagW: | |
| 2116 case MethodRecognizer::kInt32x4GetSignMask: | |
| 2117 ASSERT(call->ic_data()->HasReceiverClassId(kInt32x4Cid)); | |
| 2118 ASSERT(call->ic_data()->HasOneTarget()); | |
| 2119 return InlineInt32x4Getter(call, recognized_kind); | |
| 2120 | |
| 2121 case MethodRecognizer::kInt32x4Select: { | |
| 2122 Definition* mask = call->ArgumentAt(0); | |
| 2123 Definition* trueValue = call->ArgumentAt(1); | |
| 2124 Definition* falseValue = call->ArgumentAt(2); | |
| 2125 // Type check left. | |
| 2126 AddCheckClass(mask, | |
| 2127 ICData::ZoneHandle( | |
| 2128 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2129 call->deopt_id(), | |
| 2130 call->env(), | |
| 2131 call); | |
| 2132 Int32x4SelectInstr* select = new(Z) Int32x4SelectInstr( | |
| 2133 new(Z) Value(mask), | |
| 2134 new(Z) Value(trueValue), | |
| 2135 new(Z) Value(falseValue), | |
| 2136 call->deopt_id()); | |
| 2137 ReplaceCall(call, select); | |
| 2138 return true; | |
| 2139 } | |
| 2140 case MethodRecognizer::kInt32x4WithFlagX: | |
| 2141 case MethodRecognizer::kInt32x4WithFlagY: | |
| 2142 case MethodRecognizer::kInt32x4WithFlagZ: | |
| 2143 case MethodRecognizer::kInt32x4WithFlagW: { | |
| 2144 Definition* left = call->ArgumentAt(0); | |
| 2145 Definition* flag = call->ArgumentAt(1); | |
| 2146 // Type check left. | |
| 2147 AddCheckClass(left, | |
| 2148 ICData::ZoneHandle( | |
| 2149 Z, call->ic_data()->AsUnaryClassChecksForArgNr(0)), | |
| 2150 call->deopt_id(), | |
| 2151 call->env(), | |
| 2152 call); | |
| 2153 Int32x4SetFlagInstr* setFlag = new(Z) Int32x4SetFlagInstr( | |
| 2154 recognized_kind, | |
| 2155 new(Z) Value(left), | |
| 2156 new(Z) Value(flag), | |
| 2157 call->deopt_id()); | |
| 2158 ReplaceCall(call, setFlag); | |
| 2159 return true; | |
| 2160 } | |
| 2161 default: | |
| 2162 return false; | |
| 2163 } | |
| 2164 } | |
| 2165 | |
| 2166 | |
| 2167 // If type tests specified by 'ic_data' do not depend on type arguments, | 1668 // If type tests specified by 'ic_data' do not depend on type arguments, |
| 2168 // return mapping cid->result in 'results' (i : cid; i + 1: result). | 1669 // return mapping cid->result in 'results' (i : cid; i + 1: result). |
| 2169 // If all tests yield the same result, return it otherwise return Bool::null. | 1670 // If all tests yield the same result, return it otherwise return Bool::null. |
| 2170 // If no mapping is possible, 'results' is empty. | 1671 // If no mapping is possible, 'results' is empty. |
| 2171 // An instance-of test returning all same results can be converted to a class | 1672 // An instance-of test returning all same results can be converted to a class |
| 2172 // check. | 1673 // check. |
| 2173 RawBool* JitOptimizer::InstanceOfAsBool( | 1674 RawBool* JitOptimizer::InstanceOfAsBool( |
| 2174 const ICData& ic_data, | 1675 const ICData& ic_data, |
| 2175 const AbstractType& type, | 1676 const AbstractType& type, |
| 2176 ZoneGrowableArray<intptr_t>* results) const { | 1677 ZoneGrowableArray<intptr_t>* results) const { |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2630 new(Z) Value(call->ArgumentAt(0)), | 2131 new(Z) Value(call->ArgumentAt(0)), |
| 2631 call->deopt_id()); | 2132 call->deopt_id()); |
| 2632 ReplaceCall(call, math_unary); | 2133 ReplaceCall(call, math_unary); |
| 2633 return; | 2134 return; |
| 2634 } | 2135 } |
| 2635 switch (recognized_kind) { | 2136 switch (recognized_kind) { |
| 2636 case MethodRecognizer::kFloat32x4Zero: | 2137 case MethodRecognizer::kFloat32x4Zero: |
| 2637 case MethodRecognizer::kFloat32x4Splat: | 2138 case MethodRecognizer::kFloat32x4Splat: |
| 2638 case MethodRecognizer::kFloat32x4Constructor: | 2139 case MethodRecognizer::kFloat32x4Constructor: |
| 2639 case MethodRecognizer::kFloat32x4FromFloat64x2: | 2140 case MethodRecognizer::kFloat32x4FromFloat64x2: |
| 2640 TryInlineFloat32x4Constructor(call, recognized_kind); | |
| 2641 break; | |
| 2642 case MethodRecognizer::kFloat64x2Constructor: | 2141 case MethodRecognizer::kFloat64x2Constructor: |
| 2643 case MethodRecognizer::kFloat64x2Zero: | 2142 case MethodRecognizer::kFloat64x2Zero: |
| 2644 case MethodRecognizer::kFloat64x2Splat: | 2143 case MethodRecognizer::kFloat64x2Splat: |
| 2645 case MethodRecognizer::kFloat64x2FromFloat32x4: | 2144 case MethodRecognizer::kFloat64x2FromFloat32x4: |
| 2646 TryInlineFloat64x2Constructor(call, recognized_kind); | |
| 2647 break; | |
| 2648 case MethodRecognizer::kInt32x4BoolConstructor: | 2145 case MethodRecognizer::kInt32x4BoolConstructor: |
| 2649 case MethodRecognizer::kInt32x4Constructor: | 2146 case MethodRecognizer::kInt32x4Constructor: |
| 2650 TryInlineInt32x4Constructor(call, recognized_kind); | 2147 FlowGraphInliner::TryReplaceStaticCallWithInline( |
| 2148 flow_graph_, current_iterator(), call); |
| 2651 break; | 2149 break; |
| 2652 case MethodRecognizer::kObjectConstructor: { | 2150 case MethodRecognizer::kObjectConstructor: { |
| 2653 // Remove the original push arguments. | 2151 // Remove the original push arguments. |
| 2654 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 2152 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 2655 PushArgumentInstr* push = call->PushArgumentAt(i); | 2153 PushArgumentInstr* push = call->PushArgumentAt(i); |
| 2656 push->ReplaceUsesWith(push->value()->definition()); | 2154 push->ReplaceUsesWith(push->value()->definition()); |
| 2657 push->RemoveFromGraph(); | 2155 push->RemoveFromGraph(); |
| 2658 } | 2156 } |
| 2659 // Manually replace call with global null constant. ReplaceCall can't | 2157 // Manually replace call with global null constant. ReplaceCall can't |
| 2660 // be used for definitions that are already in the graph. | 2158 // be used for definitions that are already in the graph. |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2949 | 2447 |
| 2950 // Discard the environment from the original instruction because the store | 2448 // Discard the environment from the original instruction because the store |
| 2951 // can't deoptimize. | 2449 // can't deoptimize. |
| 2952 instr->RemoveEnvironment(); | 2450 instr->RemoveEnvironment(); |
| 2953 ReplaceCall(instr, store); | 2451 ReplaceCall(instr, store); |
| 2954 return true; | 2452 return true; |
| 2955 } | 2453 } |
| 2956 | 2454 |
| 2957 | 2455 |
| 2958 } // namespace dart | 2456 } // namespace dart |
| OLD | NEW |